1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "cache.h" 2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../builtin.h" 3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "exec_cmd.h" 4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "levenshtein.h" 5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "help.h" 6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid add_cmdname(struct cmdnames *cmds, const char *name, size_t len) 8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct cmdname *ent = malloc(sizeof(*ent) + len + 1); 10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ent->len = len; 12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memcpy(ent->name, name, len); 13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ent->name[len] = 0; 14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ALLOC_GROW(cmds->names, cmds->cnt + 1, cmds->alloc); 16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmds->names[cmds->cnt++] = ent; 17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void clean_cmdnames(struct cmdnames *cmds) 20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned int i; 22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < cmds->cnt; ++i) 24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(cmds->names[i]); 25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(cmds->names); 26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmds->cnt = 0; 27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmds->alloc = 0; 28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int cmdname_compare(const void *a_, const void *b_) 31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct cmdname *a = *(struct cmdname **)a_; 33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct cmdname *b = *(struct cmdname **)b_; 34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return strcmp(a->name, b->name); 35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void uniq(struct cmdnames *cmds) 38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned int i, j; 40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!cmds->cnt) 42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = j = 1; i < cmds->cnt; i++) 45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (strcmp(cmds->names[i]->name, cmds->names[i-1]->name)) 46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmds->names[j++] = cmds->names[i]; 47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmds->cnt = j; 49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) 52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t ci, cj, ei; 54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int cmp; 55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ci = cj = ei = 0; 57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (ci < cmds->cnt && ei < excludes->cnt) { 58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name); 59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cmp < 0) 60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmds->names[cj++] = cmds->names[ci++]; 61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (cmp == 0) 62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ci++, ei++; 63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (cmp > 0) 64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ei++; 65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (ci < cmds->cnt) 68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmds->names[cj++] = cmds->names[ci++]; 69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmds->cnt = cj; 71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void pretty_print_string_list(struct cmdnames *cmds, int longest) 74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int cols = 1, rows; 76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int space = longest + 1; /* min 1 SP between words */ 77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int max_cols; 78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i, j; 79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* ANDROID_CHANGE_BEGIN */ 80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#ifdef __BIONIC__ 81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng max_cols = 75; 82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#else 83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct winsize win; 84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng get_term_dimensions(&win); 86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng max_cols = win.ws_col - 1; /* don't print *on* the edge */ 87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif 88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* ANDROID_CHANGE_END */ 89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (space < max_cols) 91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cols = max_cols / space; 92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rows = (cmds->cnt + cols - 1) / cols; 93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < rows; i++) { 95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(" "); 96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (j = 0; j < cols; j++) { 98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned int n = j * rows + i; 99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned int size = space; 100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (n >= cmds->cnt) 102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (j == cols-1 || n + rows >= cmds->cnt) 104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size = 1; 105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("%-*s", size, cmds->names[n]->name); 106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng putchar('\n'); 108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int is_executable(const char *name) 112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct stat st; 114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (stat(name, &st) || /* stat, not lstat */ 116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng !S_ISREG(st.st_mode)) 117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return st.st_mode & S_IXUSR; 120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void list_commands_in_dir(struct cmdnames *cmds, 123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *path, 124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *prefix) 125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int prefix_len; 127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng DIR *dir = opendir(path); 128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct dirent *de; 129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct strbuf buf = STRBUF_INIT; 130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int len; 131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!dir) 133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!prefix) 135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng prefix = "perf-"; 136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng prefix_len = strlen(prefix); 137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strbuf_addf(&buf, "%s/", path); 139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng len = buf.len; 140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while ((de = readdir(dir)) != NULL) { 142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int entlen; 143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (prefixcmp(de->d_name, prefix)) 145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strbuf_setlen(&buf, len); 148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strbuf_addstr(&buf, de->d_name); 149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!is_executable(buf.buf)) 150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng entlen = strlen(de->d_name) - prefix_len; 153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (has_extension(de->d_name, ".exe")) 154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng entlen -= 4; 155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng add_cmdname(cmds, de->d_name + prefix_len, entlen); 157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng closedir(dir); 159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strbuf_release(&buf); 160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid load_command_list(const char *prefix, 163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct cmdnames *main_cmds, 164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct cmdnames *other_cmds) 165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *env_path = getenv("PATH"); 167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *exec_path = perf_exec_path(); 168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (exec_path) { 170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_commands_in_dir(main_cmds, exec_path, prefix); 171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng qsort(main_cmds->names, main_cmds->cnt, 172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sizeof(*main_cmds->names), cmdname_compare); 173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng uniq(main_cmds); 174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (env_path) { 177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *paths, *path, *colon; 178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng path = paths = strdup(env_path); 179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (1) { 180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if ((colon = strchr(path, PATH_SEP))) 181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *colon = 0; 182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!exec_path || strcmp(path, exec_path)) 183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_commands_in_dir(other_cmds, path, prefix); 184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!colon) 186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng path = colon + 1; 188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(paths); 190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng qsort(other_cmds->names, other_cmds->cnt, 192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sizeof(*other_cmds->names), cmdname_compare); 193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng uniq(other_cmds); 194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng exclude_cmds(other_cmds, main_cmds); 196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid list_commands(const char *title, struct cmdnames *main_cmds, 199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct cmdnames *other_cmds) 200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned int i, longest = 0; 202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < main_cmds->cnt; i++) 204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (longest < main_cmds->names[i]->len) 205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng longest = main_cmds->names[i]->len; 206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < other_cmds->cnt; i++) 207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (longest < other_cmds->names[i]->len) 208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng longest = other_cmds->names[i]->len; 209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (main_cmds->cnt) { 211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *exec_path = perf_exec_path(); 212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("available %s in '%s'\n", title, exec_path); 213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("----------------"); 214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng mput_char('-', strlen(title) + strlen(exec_path)); 215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng putchar('\n'); 216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pretty_print_string_list(main_cmds, longest); 217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng putchar('\n'); 218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (other_cmds->cnt) { 221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("%s available from elsewhere on your $PATH\n", title); 222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("---------------------------------------"); 223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng mput_char('-', strlen(title)); 224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng putchar('\n'); 225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pretty_print_string_list(other_cmds, longest); 226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng putchar('\n'); 227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint is_in_cmdlist(struct cmdnames *c, const char *s) 231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned int i; 233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < c->cnt; i++) 235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!strcmp(s, c->names[i]->name)) 236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 1; 237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int autocorrect; 241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct cmdnames aliases; 242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int perf_unknown_cmd_config(const char *var, const char *value, void *cb) 244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!strcmp(var, "help.autocorrect")) 246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng autocorrect = perf_config_int(var,value); 247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Also use aliases for command lookup */ 248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!prefixcmp(var, "alias.")) 249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng add_cmdname(&aliases, var + 6, strlen(var + 6)); 250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return perf_default_config(var, value, cb); 252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int levenshtein_compare(const void *p1, const void *p2) 255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const struct cmdname *const *c1 = p1, *const *c2 = p2; 257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *s1 = (*c1)->name, *s2 = (*c2)->name; 258e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int l1 = (*c1)->len; 259e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int l2 = (*c2)->len; 260e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return l1 != l2 ? l1 - l2 : strcmp(s1, s2); 261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 262e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 263e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) 264e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 265e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned int i; 266e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc); 268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < old->cnt; i++) 270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmds->names[cmds->cnt++] = old->names[i]; 271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(old->names); 272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng old->cnt = 0; 273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng old->names = NULL; 274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengconst char *help_unknown_cmd(const char *cmd) 277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned int i, n = 0, best_similarity = 0; 279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct cmdnames main_cmds, other_cmds; 280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(&main_cmds, 0, sizeof(main_cmds)); 282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(&other_cmds, 0, sizeof(main_cmds)); 283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(&aliases, 0, sizeof(aliases)); 284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng perf_config(perf_unknown_cmd_config, NULL); 286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng load_command_list("perf-", &main_cmds, &other_cmds); 288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng add_cmd_list(&main_cmds, &aliases); 290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng add_cmd_list(&main_cmds, &other_cmds); 291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng qsort(main_cmds.names, main_cmds.cnt, 292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sizeof(main_cmds.names), cmdname_compare); 293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng uniq(&main_cmds); 294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (main_cmds.cnt) { 296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* This reuses cmdname->len for similarity index */ 297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < main_cmds.cnt; ++i) 298e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng main_cmds.names[i]->len = 299e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng levenshtein(cmd, main_cmds.names[i]->name, 0, 2, 1, 4); 300e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 301e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng qsort(main_cmds.names, main_cmds.cnt, 302e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sizeof(*main_cmds.names), levenshtein_compare); 303e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 304e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng best_similarity = main_cmds.names[0]->len; 305e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng n = 1; 306e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (n < main_cmds.cnt && best_similarity == main_cmds.names[n]->len) 307e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ++n; 308e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 309e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 310e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (autocorrect && n == 1) { 311e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *assumed = main_cmds.names[0]->name; 312e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 313e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng main_cmds.names[0] = NULL; 314e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng clean_cmdnames(&main_cmds); 315e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fprintf(stderr, "WARNING: You called a perf program named '%s', " 316e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "which does not exist.\n" 317e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "Continuing under the assumption that you meant '%s'\n", 318e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmd, assumed); 319e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (autocorrect > 0) { 320e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fprintf(stderr, "in %0.1f seconds automatically...\n", 321e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (float)autocorrect/10.0); 322e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng poll(NULL, 0, autocorrect * 100); 323e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 324e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return assumed; 325e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 326e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 327e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fprintf(stderr, "perf: '%s' is not a perf-command. See 'perf --help'.\n", cmd); 328e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 329e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (main_cmds.cnt && best_similarity < 6) { 330e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fprintf(stderr, "\nDid you mean %s?\n", 331e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng n < 2 ? "this": "one of these"); 332e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 333e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < n; i++) 334e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fprintf(stderr, "\t%s\n", main_cmds.names[i]->name); 335e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 336e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 337e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng exit(1); 338e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 339e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 340e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint cmd_version(int argc __used, const char **argv __used, const char *prefix __used) 341e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 342e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("perf version %s\n", perf_version_string); 343e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 344e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 345