/* return true if 'path' exists, false otherwise */ staticbool is_present(constchar *path)
{ struct stat st;
return !stat(path, &st);
}
/* return true if 'path' exists and it is a directory, false otherwise */ staticbool is_dir(constchar *path)
{ struct stat st;
if (stat(path, &st)) returnfalse;
return S_ISDIR(st.st_mode);
}
/* return true if the given two files are the same, false otherwise */ staticbool is_same(constchar *file1, constchar *file2)
{ int fd1, fd2; struct stat st1, st2; void *map1, *map2; bool ret = false;
fd1 = open(file1, O_RDONLY); if (fd1 < 0) return ret;
fd2 = open(file2, O_RDONLY); if (fd2 < 0) goto close1;
ret = fstat(fd1, &st1); if (ret) goto close2;
ret = fstat(fd2, &st2); if (ret) goto close2;
ret = true;
close2:
close(fd2);
close1:
close(fd1);
return ret;
}
/* * Create the parent directory of the given path. * * For example, if 'include/config/auto.conf' is given, create 'include/config'.
*/ staticint make_parent_dir(constchar *path)
{ char tmp[PATH_MAX + 1]; char *p;
return name ? name : "include/generated/rustc_cfg";
}
staticint conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
{ char *p2;
switch (sym->type) { case S_TRISTATE: if (p[0] == 'm') {
sym->def[def].tri = mod;
sym->flags |= def_flags; break;
} /* fall through */ case S_BOOLEAN: if (p[0] == 'y') {
sym->def[def].tri = yes;
sym->flags |= def_flags; break;
} if (p[0] == 'n') {
sym->def[def].tri = no;
sym->flags |= def_flags; break;
} if (def != S_DEF_AUTO)
conf_warning("symbol value '%s' invalid for %s",
p, sym->name); return 1; case S_STRING: /* No escaping for S_DEF_AUTO (include/config/auto.conf) */ if (def != S_DEF_AUTO) { if (*p++ != '"') break; for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { if (*p2 == '"') {
*p2 = 0; break;
}
memmove(p2, p2 + 1, strlen(p2));
} if (!p2) {
conf_warning("invalid string found"); return 1;
}
} /* fall through */ case S_INT: case S_HEX: if (sym_string_valid(sym, p)) {
sym->def[def].val = xstrdup(p);
sym->flags |= def_flags;
} else { if (def != S_DEF_AUTO)
conf_warning("symbol value '%s' invalid for %s",
p, sym->name); return 1;
} break; default:
;
} return 0;
}
/* like getline(), but the newline character is stripped away */ static ssize_t getline_stripped(char **lineptr, size_t *n, FILE *stream)
{
ssize_t len;
while (getline_stripped(&line, &line_asize, in) != -1) { struct menu *choice;
conf_lineno++;
if (!line[0]) /* blank line */ continue;
if (line[0] == '#') { if (line[1] != ' ') continue;
p = line + 2; if (memcmp(p, CONFIG_, strlen(CONFIG_))) continue;
sym_name = p + strlen(CONFIG_);
p = strchr(sym_name, ' '); if (!p) continue;
*p++ = 0; if (strcmp(p, "is not set")) continue;
val = "n";
} else { if (memcmp(line, CONFIG_, strlen(CONFIG_))) {
conf_warning("unexpected data: %s", line); continue;
}
sym_name = line + strlen(CONFIG_);
p = strchr(sym_name, '='); if (!p) {
conf_warning("unexpected data: %s", line); continue;
}
*p = 0;
val = p + 1;
}
sym = sym_find(sym_name); if (!sym) { if (def == S_DEF_AUTO) { /* * Reading from include/config/auto.conf. * If CONFIG_FOO previously existed in auto.conf * but it is missing now, include/config/FOO * must be touched.
*/
conf_touch_dep(sym_name);
} else { if (warn_unknown)
conf_warning("unknown symbol: %s", sym_name);
conf_set_changed(true);
} continue;
}
if (sym->flags & def_flags)
conf_warning("override: reassigning to symbol %s", sym->name);
if (conf_set_sym_val(sym, def, def_flags, val)) continue;
if (def != S_DEF_USER) continue;
/* * If this is a choice member, give it the highest priority. * If conflicting CONFIG options are given from an input file, * the last one wins.
*/
choice = sym_get_choice_menu(sym); if (choice)
list_move(&sym->choice_link, &choice->choice_members);
}
free(line);
fclose(in);
return 0;
}
int conf_read(constchar *name)
{ struct symbol *sym;
conf_set_changed(false);
if (conf_read_simple(name, S_DEF_USER)) {
sym_calc_value(modules_sym); return 1;
}
sym_calc_value(modules_sym);
for_all_symbols(sym) {
sym_calc_value(sym); if (sym_is_choice(sym)) continue; if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { /* check that calculated value agrees with saved value */ switch (sym->type) { case S_BOOLEAN: case S_TRISTATE: if (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym)) continue; break; default: if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) continue; break;
}
} elseif (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) /* no previous value and not saved */ continue;
conf_set_changed(true); /* maybe print value in verbose mode... */
}
switch (sym->type) { case S_BOOLEAN: case S_TRISTATE: /* * We do not care about disabled ones, i.e. no need for * what otherwise are "comments" in other printers.
*/ if (*val == 'n') return;
/* * To have similar functionality to the C macro `IS_ENABLED()` * we provide an empty `--cfg CONFIG_X` here in both `y` * and `m` cases. * * Then, the common `fprintf()` below will also give us * a `--cfg CONFIG_X="y"` or `--cfg CONFIG_X="m"`, which can * be used as the equivalent of `IS_BUILTIN()`/`IS_MODULE()`.
*/
fprintf(fp, "--cfg=%s%s\n", CONFIG_, sym->name); break; case S_HEX: if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X'))
val_prefix = "0x"; break; default: break;
}
/* * Write out a minimal config. * All values that has default values are skipped as this is redundant.
*/ int conf_write_defconfig(constchar *filename)
{ struct symbol *sym; struct menu *menu;
FILE *out;
out = fopen(filename, "w"); if (!out) return 1;
sym_clear_all_valid();
menu_for_each_entry(menu) { struct menu *choice;
sym = menu->sym;
if (!sym || sym_is_choice(sym)) continue;
sym_calc_value(sym); if (!(sym->flags & SYMBOL_WRITE)) continue;
sym->flags &= ~SYMBOL_WRITE; /* Skip unchangeable symbols */ if (!sym_is_changeable(sym)) continue; /* Skip symbols that are equal to the default */ if (!strcmp(sym_get_string_value(sym), sym_get_string_default(sym))) continue;
/* Skip choice values that are equal to the default */
choice = sym_get_choice_menu(sym); if (choice) { struct symbol *ds;
conf_message("configuration written to %s", name);
conf_set_changed(false);
return 0;
}
/* write a dependency file as used by kbuild to track dependencies */ staticint conf_write_autoconf_cmd(constchar *autoconf_name)
{ char name[PATH_MAX], tmp[PATH_MAX];
FILE *out; int ret;
ret = snprintf(name, sizeof(name), "%s.cmd", autoconf_name); if (ret >= sizeof(name)) /* check truncation */ return -1;
if (make_parent_dir(name)) return -1;
ret = snprintf(tmp, sizeof(tmp), "%s.cmd.tmp", autoconf_name); if (ret >= sizeof(tmp)) /* check truncation */ return -1;
out = fopen(tmp, "w"); if (!out) {
perror("fopen"); return -1;
}
for_all_symbols(sym) { if (sym_is_choice(sym)) continue; if (sym->flags & SYMBOL_WRITE) { if (sym->flags & SYMBOL_DEF_AUTO) { /* * symbol has old and new value, * so compare them...
*/ switch (sym->type) { case S_BOOLEAN: case S_TRISTATE: if (sym_get_tristate_value(sym) ==
sym->def[S_DEF_AUTO].tri) continue; break; case S_STRING: case S_HEX: case S_INT: if (!strcmp(sym_get_string_value(sym),
sym->def[S_DEF_AUTO].val)) continue; break; default: break;
}
} else { /* * If there is no old value, only 'no' (unset) * is allowed as new value.
*/ switch (sym->type) { case S_BOOLEAN: case S_TRISTATE: if (sym_get_tristate_value(sym) == no) continue; break; default: break;
}
}
} elseif (!(sym->flags & SYMBOL_DEF_AUTO)) /* There is neither an old nor a new value. */ continue; /* else * There is an old value, but no new value ('no' (unset) * isn't saved in auto.conf, so the old value is always * different from 'no').
*/
res = conf_touch_dep(sym->name); if (res) return res;
}
return 0;
}
staticint __conf_write_autoconf(constchar *filename, void (*print_symbol)(FILE *, struct symbol *), conststruct comment_style *comment_style)
{ char tmp[PATH_MAX];
FILE *file; struct symbol *sym; int ret;
if (make_parent_dir(filename)) return -1;
ret = snprintf(tmp, sizeof(tmp), "%s.tmp", filename); if (ret >= sizeof(tmp)) /* check truncation */ return -1;
for_all_symbols(sym) if ((sym->flags & SYMBOL_WRITE) && sym->name)
print_symbol(file, sym);
fflush(file); /* check possible errors in conf_write_heading() and print_symbol() */
ret = ferror(file);
fclose(file); if (ret) return -1;
if (rename(tmp, filename)) {
perror("rename"); return -1;
}
return 0;
}
int conf_write_autoconf(int overwrite)
{ struct symbol *sym; constchar *autoconf_name = conf_get_autoconfig_name(); int ret;
if (!overwrite && is_present(autoconf_name)) return 0;
ret = conf_write_autoconf_cmd(autoconf_name); if (ret) return -1;
for_all_symbols(sym)
sym_calc_value(sym);
if (conf_touch_deps()) return 1;
ret = __conf_write_autoconf(conf_get_autoheader_name(),
print_symbol_for_c,
&comment_style_c); if (ret) return ret;
ret = __conf_write_autoconf(conf_get_rustccfg_name(),
print_symbol_for_rustccfg,
NULL); if (ret) return ret;
/* * Create include/config/auto.conf. This must be the last step because * Kbuild has a dependency on auto.conf and this marks the successful * completion of the previous steps.
*/
ret = __conf_write_autoconf(conf_get_autoconfig_name(),
print_symbol_for_autoconf,
&comment_style_pound); if (ret) return ret;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.