///|
fn hex_text(value : Int64) -> String raise ConfigError {
if value < 0L {
raise Invalid("negative hex value")
}
if value == 0L {
return "0x0"
}
let digits = "0123456789abcdef"
let out : Array[String] = []
let mut rest = value
while rest != 0L {
let index = (rest % 16L).to_int()
out.push(digits[index:index + 1].to_owned())
rest /= 16L
}
let ordered = []
for i = out.length() - 1; i >= 0; i = i - 1 {
ordered.push(out[i])
}
"0x" + ordered.join("")
}
///|
fn config_line(
name : String,
kind : Kind,
value : Value,
) -> String raise ConfigError {
match value {
Unset => ""
Logic(N) => "# CONFIG_" + name + " is not set\n"
Logic(t) => "CONFIG_" + name + "=" + t.text() + "\n"
Text(s) => "CONFIG_" + name + "=" + quote_string(s) + "\n"
RawNumber(raw, _) => "CONFIG_" + name + "=" + raw + "\n"
Number(n) =>
"CONFIG_" +
name +
"=" +
(if kind == Hex { hex_text(n) } else { n.to_string() }) +
"\n"
}
}
///|
fn Schema::check_snapshot(
self : Schema,
result : Resolution,
) -> Unit raise ConfigError {
if self.defs.length() != result.values.length() {
raise Invalid("snapshot/schema symbols differ")
}
for d in self.defs {
let value = result.value(d.name)
let kind = self.kind(d.name)
if value == Unset && (kind == Integer || kind == Hex) {
continue
}
if self.linux612 && value is RawNumber(_, k) && k == kind {
continue
}
if !kind.accepts(value) {
raise Invalid("snapshot/schema type differs: " + d.name)
}
}
}
///|
/// Deterministic complete value export in declaration order, with no host I/O.
pub fn Schema::export_config(
self : Schema,
result : Resolution,
) -> String raise ConfigError {
self.check_snapshot(result)
let lines = ["# Generated by MoonKconfig; do not edit derived values.\n"]
for d in self.defs {
lines.push(config_line(d.name, self.kind(d.name), result.value(d.name)))
}
lines.join("")
}
///|
/// C preprocessor header; module values use CONFIG_NAME_MODULE, not CONFIG_NAME.
pub fn Schema::export_header(
self : Schema,
result : Resolution,
) -> String raise ConfigError {
self.check_snapshot(result)
let lines = [
"/* Generated by MoonKconfig. */\n#ifndef MOONKCONFIG_GENERATED_H\n#define MOONKCONFIG_GENERATED_H\n",
]
for d in self.defs {
let value = result.value(d.name)
let prefix = "#define CONFIG_" + d.name
let definition = match value {
Unset | Logic(N) => ""
Logic(Y) => prefix + " 1\n"
Logic(M) => prefix + "_MODULE 1\n"
Text(s) => prefix + " " + quote_string(s) + "\n"
RawNumber(raw, _) => prefix + " " + raw + "\n"
Number(n) =>
prefix +
" " +
(if self.kind(d.name) == Hex { hex_text(n) } else { n.to_string() }) +
"\n"
}
lines.push(definition)
}
lines.push("#endif\n")
lines.join("")
}