cregit-Linux how code gets into the kernel

Release 4.10 tools/perf/util/config.c

Directory: tools/perf/util
/*
 * config.c
 *
 * Helper functions for parsing config items.
 * Originally copied from GIT source.
 *
 * Copyright (C) Linus Torvalds, 2005
 * Copyright (C) Johannes Schindelin, 2005
 *
 */
#include "util.h"
#include "cache.h"
#include <subcmd/exec-cmd.h>
#include "util/hist.h"  /* perf_hist_config */
#include "util/llvm-utils.h"   /* perf_llvm_config */
#include "config.h"


#define MAXNAME (256)


#define DEBUG_CACHE_DIR ".debug"



char buildid_dir[MAXPATHLEN]; 
/* root dir for buildid, binary cache */


static FILE *config_file;

static const char *config_file_name;

static int config_linenr;

static int config_file_eof;

static struct perf_config_set *config_set;


const char *config_exclusive_filename;


static int get_next_char(void) { int c; FILE *f; c = '\n'; if ((f = config_file) != NULL) { c = fgetc(f); if (c == '\r') { /* DOS like systems */ c = fgetc(f); if (c != '\n') { ungetc(c, f); c = '\r'; } } if (c == '\n') config_linenr++; if (c == EOF) { config_file_eof = 1; c = '\n'; } } return c; }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar101100.00%1100.00%
Total101100.00%1100.00%


static char *parse_value(void) { static char value[1024]; int quote = 0, comment = 0, space = 0; size_t len = 0; for (;;) { int c = get_next_char(); if (len >= sizeof(value) - 1) return NULL; if (c == '\n') { if (quote) return NULL; value[len] = 0; return value; } if (comment) continue; if (isspace(c) && !quote) { space = 1; continue; } if (!quote) { if (c == ';' || c == '#') { comment = 1; continue; } } if (space) { if (len) value[len++] = ' '; space = 0; } if (c == '\\') { c = get_next_char(); switch (c) { case '\n': continue; case 't': c = '\t'; break; case 'b': c = '\b'; break; case 'n': c = '\n'; break; /* Some characters escape as themselves */ case '\\': case '"': break; /* Reject unknown escape sequences */ default: return NULL; } value[len++] = c; continue; } if (c == '"') { quote = 1-quote; continue; } value[len++] = c; } }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar246100.00%2100.00%
Total246100.00%2100.00%


static inline int iskeychar(int c) { return isalnum(c) || c == '-' || c == '_'; }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar2083.33%150.00%
arnaldo carvalho de meloarnaldo carvalho de melo416.67%150.00%
Total24100.00%2100.00%


static int get_value(config_fn_t fn, void *data, char *name, unsigned int len) { int c; char *value; /* Get the full name */ for (;;) { c = get_next_char(); if (config_file_eof) break; if (!iskeychar(c)) break; name[len++] = c; if (len >= MAXNAME) return -1; } name[len] = 0; while (c == ' ' || c == '\t') c = get_next_char(); value = NULL; if (c != '\n') { if (c != '=') return -1; value = parse_value(); if (!value) return -1; } return fn(name, value, data); }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar141100.00%1100.00%
Total141100.00%1100.00%


static int get_extended_base_var(char *name, int baselen, int c) { do { if (c == '\n') return -1; c = get_next_char(); } while (isspace(c)); /* We require the format to be '[base "extension"]' */ if (c != '"') return -1; name[baselen++] = '.'; for (;;) { int ch = get_next_char(); if (ch == '\n') return -1; if (ch == '"') break; if (ch == '\\') { ch = get_next_char(); if (ch == '\n') return -1; } name[baselen++] = ch; if (baselen > MAXNAME / 2) return -1; } /* Final ']' */ if (get_next_char() != ']') return -1; return baselen; }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar149100.00%2100.00%
Total149100.00%2100.00%


static int get_base_var(char *name) { int baselen = 0; for (;;) { int c = get_next_char(); if (config_file_eof) return -1; if (c == ']') return baselen; if (isspace(c)) return get_extended_base_var(name, baselen, c); if (!iskeychar(c) && c != '.') return -1; if (baselen > MAXNAME / 2) return -1; name[baselen++] = tolower(c); } }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar101100.00%1100.00%
Total101100.00%1100.00%


static int perf_parse_file(config_fn_t fn, void *data) { int comment = 0; int baselen = 0; static char var[MAXNAME]; /* U+FEFF Byte Order Mark in UTF8 */ static const unsigned char *utf8_bom = (unsigned char *) "\xef\xbb\xbf"; const unsigned char *bomptr = utf8_bom; for (;;) { int line, c = get_next_char(); if (bomptr && *bomptr) { /* We are at the file beginning; skip UTF8-encoded BOM * if present. Sane editors won't put this in on their * own, but e.g. Windows Notepad will do it happily. */ if ((unsigned char) c == *bomptr) { bomptr++; continue; } else { /* Do not tolerate partial BOM. */ if (bomptr != utf8_bom) break; /* No BOM at file beginning. Cool. */ bomptr = NULL; } } if (c == '\n') { if (config_file_eof) return 0; comment = 0; continue; } if (comment || isspace(c)) continue; if (c == '#' || c == ';') { comment = 1; continue; } if (c == '[') { baselen = get_base_var(var); if (baselen <= 0) break; var[baselen++] = '.'; var[baselen] = 0; continue; } if (!isalpha(c)) break; var[baselen] = tolower(c); /* * The get_value function might or might not reach the '\n', * so saving the current line number for error reporting. */ line = config_linenr; if (get_value(fn, data, var, baselen+1) < 0) { config_linenr = line; break; } } pr_err("bad config file line %d in %s\n", config_linenr, config_file_name); return -1; }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar23892.61%133.33%
jiri olsajiri olsa135.06%133.33%
taeung songtaeung song62.33%133.33%
Total257100.00%3100.00%


static int parse_unit_factor(const char *end, unsigned long *val) { if (!*end) return 1; else if (!strcasecmp(end, "k")) { *val *= 1024; return 1; } else if (!strcasecmp(end, "m")) { *val *= 1024 * 1024; return 1; } else if (!strcasecmp(end, "g")) { *val *= 1024 * 1024 * 1024; return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar97100.00%1100.00%
Total97100.00%1100.00%


static int perf_parse_llong(const char *value, long long *ret) { if (value && *value) { char *end; long long val = strtoll(value, &end, 0); unsigned long factor = 1; if (!parse_unit_factor(end, &factor)) return 0; *ret = val * factor; return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
jiri olsajiri olsa76100.00%1100.00%
Total76100.00%1100.00%


static int perf_parse_long(const char *value, long *ret) { if (value && *value) { char *end; long val = strtol(value, &end, 0); unsigned long factor = 1; if (!parse_unit_factor(end, &factor)) return 0; *ret = val * factor; return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar74100.00%1100.00%
Total74100.00%1100.00%


static void die_bad_config(const char *name) { if (config_file_name) die("bad config value for '%s' in %s", name, config_file_name); die("bad config value for '%s'", name); }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar31100.00%1100.00%
Total31100.00%1100.00%


u64 perf_config_u64(const char *name, const char *value) { long long ret = 0; if (!perf_parse_llong(value, &ret)) die_bad_config(name); return (u64) ret; }

Contributors

PersonTokensPropCommitsCommitProp
jiri olsajiri olsa43100.00%1100.00%
Total43100.00%1100.00%


int perf_config_int(const char *name, const char *value) { long ret = 0; if (!perf_parse_long(value, &ret)) die_bad_config(name); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar39100.00%1100.00%
Total39100.00%1100.00%


static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool) { *is_bool = 1; if (!value) return 1; if (!*value) return 0; if (!strcasecmp(value, "true") || !strcasecmp(value, "yes") || !strcasecmp(value, "on")) return 1; if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off")) return 0; *is_bool = 0; return perf_config_int(name, value); }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar11299.12%150.00%
arnaldo carvalho de meloarnaldo carvalho de melo10.88%150.00%
Total113100.00%2100.00%


int perf_config_bool(const char *name, const char *value) { int discard; return !!perf_config_bool_or_int(name, value, &discard); }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar31100.00%1100.00%
Total31100.00%1100.00%


static const char *perf_config_dirname(const char *name, const char *value) { if (!name) return NULL; return value; }

Contributors

PersonTokensPropCommitsCommitProp
stephane eranianstephane eranian2896.55%150.00%
arnaldo carvalho de meloarnaldo carvalho de melo13.45%150.00%
Total29100.00%2100.00%


static int perf_buildid_config(const char *var, const char *value) { /* same dir for all commands */ if (!strcmp(var, "buildid.dir")) { const char *dir = perf_config_dirname(var, value); if (!dir) return -1; strncpy(buildid_dir, dir, MAXPATHLEN-1); buildid_dir[MAXPATHLEN-1] = '\0'; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song7095.89%150.00%
vinson leevinson lee34.11%150.00%
Total73100.00%2100.00%


static int perf_default_core_config(const char *var __maybe_unused, const char *value __maybe_unused) { /* Add other config variables here. */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar1986.36%133.33%
irina tirdeairina tirdea29.09%133.33%
paul bollepaul bolle14.55%133.33%
Total22100.00%3100.00%


static int perf_ui_config(const char *var, const char *value) { /* Add other config variables here. */ if (!strcmp(var, "ui.show-headers")) { symbol_conf.show_hist_headers = perf_config_bool(var, value); return 0; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
jiri olsajiri olsa46100.00%1100.00%
Total46100.00%1100.00%


int perf_default_config(const char *var, const char *value, void *dummy __maybe_unused) { if (!prefixcmp(var, "core.")) return perf_default_core_config(var, value); if (!prefixcmp(var, "hist.")) return perf_hist_config(var, value); if (!prefixcmp(var, "ui.")) return perf_ui_config(var, value); if (!prefixcmp(var, "call-graph.")) return perf_callchain_config(var, value); if (!prefixcmp(var, "llvm.")) return perf_llvm_config(var, value); if (!prefixcmp(var, "buildid.")) return perf_buildid_config(var, value); /* Add other config variables here. */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar4030.30%112.50%
namhyung kimnamhyung kim3627.27%225.00%
jiri olsajiri olsa1813.64%112.50%
wang nanwang nan1813.64%112.50%
taeung songtaeung song1813.64%112.50%
paul bollepaul bolle10.76%112.50%
irina tirdeairina tirdea10.76%112.50%
Total132100.00%8100.00%


static int perf_config_from_file(config_fn_t fn, const char *filename, void *data) { int ret; FILE *f = fopen(filename, "r"); ret = -1; if (f) { config_file = f; config_file_name = filename; config_linenr = 1; config_file_eof = 0; ret = perf_parse_file(fn, data); fclose(f); config_file_name = NULL; } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar7998.75%150.00%
arnaldo carvalho de meloarnaldo carvalho de melo11.25%150.00%
Total80100.00%2100.00%


const char *perf_etc_perfconfig(void) { static const char *system_wide; if (!system_wide) system_wide = system_path(ETC_PERFCONFIG); return system_wide; }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar30100.00%1100.00%
Total30100.00%1100.00%


static int perf_env_bool(const char *k, int def) { const char *v = getenv(k); return v ? perf_config_bool(k, v) : def; }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar36100.00%1100.00%
Total36100.00%1100.00%


static int perf_config_system(void) { return !perf_env_bool("PERF_CONFIG_NOSYSTEM", 0); }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar1694.12%150.00%
arnaldo carvalho de meloarnaldo carvalho de melo15.88%150.00%
Total17100.00%2100.00%


static int perf_config_global(void) { return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0); }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar1694.12%150.00%
arnaldo carvalho de meloarnaldo carvalho de melo15.88%150.00%
Total17100.00%2100.00%


static struct perf_config_section *find_section(struct list_head *sections, const char *section_name) { struct perf_config_section *section; list_for_each_entry(section, sections, node) if (!strcmp(section->name, section_name)) return section; return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song49100.00%1100.00%
Total49100.00%1100.00%


static struct perf_config_item *find_config_item(const char *name, struct perf_config_section *section) { struct perf_config_item *item; list_for_each_entry(item, &section->items, node) if (!strcmp(item->name, name)) return item; return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song49100.00%1100.00%
Total49100.00%1100.00%


static struct perf_config_section *add_section(struct list_head *sections, const char *section_name) { struct perf_config_section *section = zalloc(sizeof(*section)); if (!section) return NULL; INIT_LIST_HEAD(&section->items); section->name = strdup(section_name); if (!section->name) { pr_debug("%s: strdup failed\n", __func__); free(section); return NULL; } list_add_tail(&section->node, sections); return section; }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song94100.00%1100.00%
Total94100.00%1100.00%


static struct perf_config_item *add_config_item(struct perf_config_section *section, const char *name) { struct perf_config_item *item = zalloc(sizeof(*item)); if (!item) return NULL; item->name = strdup(name); if (!item->name) { pr_debug("%s: strdup failed\n", __func__); free(item); return NULL; } list_add_tail(&item->node, &section->items); return item; }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song89100.00%1100.00%
Total89100.00%1100.00%


static int set_value(struct perf_config_item *item, const char *value) { char *val = strdup(value); if (!val) return -1; zfree(&item->value); item->value = val; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song51100.00%1100.00%
Total51100.00%1100.00%


static int collect_config(const char *var, const char *value, void *perf_config_set) { int ret = -1; char *ptr, *key; char *section_name, *name; struct perf_config_section *section = NULL; struct perf_config_item *item = NULL; struct perf_config_set *set = perf_config_set; struct list_head *sections; if (set == NULL) return -1; sections = &set->sections; key = ptr = strdup(var); if (!key) { pr_debug("%s: strdup failed\n", __func__); return -1; } section_name = strsep(&ptr, "."); name = ptr; if (name == NULL || value == NULL) goto out_free; section = find_section(sections, section_name); if (!section) { section = add_section(sections, section_name); if (!section) goto out_free; } item = find_config_item(name, section); if (!item) { item = add_config_item(section, name); if (!item) goto out_free; } /* perf_config_set can contain both user and system config items. * So we should know where each value is from. * The classification would be needed when a particular config file * is overwrited by setting feature i.e. set_config(). */ if (strcmp(config_file_name, perf_etc_perfconfig()) == 0) { section->from_system_config = true; item->from_system_config = true; } else { section->from_system_config = false; item->from_system_config = false; } ret = set_value(item, value); return ret; out_free: free(key); return -1; }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song268100.00%3100.00%
Total268100.00%3100.00%


int perf_config_set__collect(struct perf_config_set *set, const char *file_name, const char *var, const char *value) { config_file_name = file_name; return collect_config(var, value, set); }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song39100.00%2100.00%
Total39100.00%2100.00%


static int perf_config_set__init(struct perf_config_set *set) { int ret = -1; const char *home = NULL; /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ if (config_exclusive_filename) return perf_config_from_file(collect_config, config_exclusive_filename, set); if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) { if (perf_config_from_file(collect_config, perf_etc_perfconfig(), set) < 0) goto out; } home = getenv("HOME"); if (perf_config_global() && home) { char *user_config = strdup(mkpath("%s/.perfconfig", home)); struct stat st; if (user_config == NULL) { warning("Not enough memory to process %s/.perfconfig, " "ignoring it.", home); goto out; } if (stat(user_config, &st) < 0) goto out_free; if (st.st_uid && (st.st_uid != geteuid())) { warning("File %s not owned by current user or root, " "ignoring it.", user_config); goto out_free; } if (!st.st_size) goto out_free; ret = perf_config_from_file(collect_config, user_config, set); out_free: free(user_config); } out: return ret; }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song201100.00%1100.00%
Total201100.00%1100.00%


struct perf_config_set *perf_config_set__new(void) { struct perf_config_set *set = zalloc(sizeof(*set)); if (set) { INIT_LIST_HEAD(&set->sections); if (perf_config_set__init(set) < 0) { perf_config_set__delete(set); set = NULL; } } return set; }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song60100.00%3100.00%
Total60100.00%3100.00%


int perf_config(config_fn_t fn, void *data) { int ret = 0; char key[BUFSIZ]; struct perf_config_section *section; struct perf_config_item *item; if (config_set == NULL) return -1; perf_config_set__for_each_entry(config_set, section, item) { char *value = item->value; if (value) { scnprintf(key, sizeof(key), "%s.%s", section->name, item->name); ret = fn(key, value, data); if (ret < 0) { pr_err("Error: wrong config key-value pair %s=%s\n", key, value); break; } } } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song119100.00%1100.00%
Total119100.00%1100.00%


void perf_config__init(void) { if (config_set == NULL) config_set = perf_config_set__new(); }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song18100.00%1100.00%
Total18100.00%1100.00%


void perf_config__exit(void) { perf_config_set__delete(config_set); config_set = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song16100.00%1100.00%
Total16100.00%1100.00%


void perf_config__refresh(void) { perf_config__exit(); perf_config__init(); }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song13100.00%1100.00%
Total13100.00%1100.00%


static void perf_config_item__delete(struct perf_config_item *item) { zfree(&item->name); zfree(&item->value); free(item); }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song32100.00%1100.00%
Total32100.00%1100.00%


static void perf_config_section__purge(struct perf_config_section *section) { struct perf_config_item *item, *tmp; list_for_each_entry_safe(item, tmp, &section->items, node) { list_del_init(&item->node); perf_config_item__delete(item); } }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song44100.00%1100.00%
Total44100.00%1100.00%


static void perf_config_section__delete(struct perf_config_section *section) { perf_config_section__purge(section); zfree(&section->name); free(section); }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song29100.00%1100.00%
Total29100.00%1100.00%


static void perf_config_set__purge(struct perf_config_set *set) { struct perf_config_section *section, *tmp; list_for_each_entry_safe(section, tmp, &set->sections, node) { list_del_init(&section->node); perf_config_section__delete(section); } }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song44100.00%1100.00%
Total44100.00%1100.00%


void perf_config_set__delete(struct perf_config_set *set) { if (set == NULL) return; perf_config_set__purge(set); free(set); }

Contributors

PersonTokensPropCommitsCommitProp
taeung songtaeung song27100.00%2100.00%
Total27100.00%2100.00%

/* * Call this to report error for your variable that should not * get a boolean value (i.e. "[my] var" means "true"). */
int config_error_nonbool(const char *var) { return error("Missing value for '%s'", var); }

Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar18100.00%1100.00%
Total18100.00%1100.00%


void set_buildid_dir(const char *dir) { if (dir) scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir); /* default to $HOME/.debug */ if (buildid_dir[0] == '\0') { char *home = getenv("HOME"); if (home) { snprintf(buildid_dir, MAXPATHLEN-1, "%s/%s", home, DEBUG_CACHE_DIR); } else { strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1); } buildid_dir[MAXPATHLEN-1] = '\0'; } /* for communicating with external commands */ setenv("PERF_BUILDID_DIR", buildid_dir, 1); }

Contributors

PersonTokensPropCommitsCommitProp
stephane eranianstephane eranian7876.47%133.33%
jiri olsajiri olsa2120.59%133.33%
taeung songtaeung song32.94%133.33%
Total102100.00%3100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
ingo molnaringo molnar167148.66%310.00%
taeung songtaeung song134839.25%1136.67%
jiri olsajiri olsa2176.32%413.33%
stephane eranianstephane eranian1173.41%13.33%
namhyung kimnamhyung kim411.19%310.00%
wang nanwang nan220.64%13.33%
arnaldo carvalho de meloarnaldo carvalho de melo90.26%310.00%
irina tirdeairina tirdea30.09%13.33%
vinson leevinson lee30.09%13.33%
paul bollepaul bolle20.06%13.33%
josh poimboeufjosh poimboeuf10.03%13.33%
Total3434100.00%30100.00%
Directory: tools/perf/util
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.