Name sets
Enumerated values of the data are numbers, and a name set, dmi_name_set_t,
gives each of them two names: a code, which the exported data and the command
line options use, and a name, which the output shows. The cache types are
named this way, in libopendmi/src/entity/cache-names.c:
const dmi_name_set_t dmi_cache_type_names =
{
.code = "cache-type",
.names = DMI_NAMES({
DMI_NAME_UNSPEC(DMI_CACHE_TYPE_UNSPEC),
DMI_NAME_OTHER(DMI_CACHE_TYPE_OTHER),
DMI_NAME_UNKNOWN(DMI_CACHE_TYPE_UNKNOWN),
{
.id = DMI_CACHE_TYPE_INSTRUCTION,
.code = "instruction",
.name = "Instruction"
},
{
.id = DMI_CACHE_TYPE_DATA,
.code = "data",
.name = "Data"
},
{
.id = DMI_CACHE_TYPE_UNIFIED,
.code = "unified",
.name = "Unified"
},
{}
})
};
The values almost every enumeration of the specification has are named by
helpers, which give them the same codes and names everywhere:
DMI_NAME_UNSPEC, DMI_NAME_UNKNOWN, DMI_NAME_OTHER, DMI_NAME_NONE,
DMI_NAME_UNSUPPORTED and DMI_NAME_RESERVED.
1. Ranges
Values the specification gives one meaning to a whole range of, e.g. the ones it leaves to the vendors, are named by ranges rather than one by one, which the name set lists after the names:
const dmi_name_set_t dmi_example_names =
{
.code = "example",
.names = DMI_NAMES({
DMI_NAME_UNKNOWN(0x00),
{
.id = 0x01,
.code = "fan",
.name = "Fan"
},
{}
}),
.ranges = DMI_NAME_RANGES({
{
.start_id = 0x80,
.end_id = 0xFF,
.code = "vendor-specific",
.name = "Vendor-specific"
},
{}
})
};
A value is looked up among the names first, and among the ranges then, so a name given to a value of a range takes precedence over the range.
2. Looking the names up
Name sets of the structure types are private to the library, which looks the
names up with dmi_code_lookup and dmi_name_lookup, giving the code and the
name of a value, or nullptr for a value the set does not name, and with
dmi_code_lookup_rev, giving the value of a code back, which is how the
options of the tool take values by their codes:
const char *code = dmi_code_lookup(&dmi_cache_type_names,
DMI_CACHE_TYPE_DATA);
const char *name = dmi_name_lookup(&dmi_cache_type_names,
DMI_CACHE_TYPE_DATA);
int id = dmi_code_lookup_rev(&dmi_cache_type_names, "unified");
A program gets the names through the functions most enumerations have, e.g.
dmi_cache_type_name, and through the attributes, which refer to the name
sets. The functions are defined with DMI_NAME_FUNCTION, see DMI_NAMES,
which names the function, the enumeration type and the name set after one
prefix:
DMI_NAME_FUNCTION(dmi_cache_type) // dmi_cache_type_name(), dmi_cache_type_t, dmi_cache_type_names
Name sets are what the attributes of the enumerated values and of the sets of
bits refer to by values, see
Describing a structure, so
a value is shown by its name and exported by its code wherever it appears, and
the lint rule value.invalid-enum reports the values a set does not name.
3. Translations
Names are translated into the locale the library is set to, when it is built
with the translations, while codes never are: they are what the data is
exchanged by. A translation is looked up by the code of the set and the code
of the value, in the resources of the locale, libopendmi/locale/ru_RU.txt
for Russian:
cache-type {
unspecified { "Не указан" }
other { "Другой" }
unknown { "Неизвестный" }
instruction { "Инструкции" }
data { "Данные" }
unified { "Унифицированный" }
}
A value the resources have no translation of is shown by the name the set gives it, so a name set works with no translations at all, and the codes of a set and of its values are all a translator needs to know. The names of the structure types and of the attributes are translated the same way, by their codes.