diff --git a/src/util/xmlconfig.c b/src/util/xmlconfig.c
index b00ae109eb7..5e6c49d2a96 100644
--- a/src/util/xmlconfig.c
+++ b/src/util/xmlconfig.c
@@ -61,262 +61,6 @@
#define PATH_MAX 4096
#endif
-/** \brief Find an option in an option cache with the name as key */
-static uint32_t
-findOption(const driOptionCache *cache, const char *name)
-{
- uint32_t len = strlen(name);
- uint32_t size = 1 << cache->tableSize, mask = size - 1;
- uint32_t hash = 0;
- uint32_t i, shift;
-
- /* compute a hash from the variable length name */
- for (i = 0, shift = 0; i < len; ++i, shift = (shift+8) & 31)
- hash += (uint32_t)name[i] << shift;
- hash *= hash;
- hash = (hash >> (16-cache->tableSize/2)) & mask;
-
- /* this is just the starting point of the linear search for the option */
- for (i = 0; i < size; ++i, hash = (hash+1) & mask) {
- /* if we hit an empty entry then the option is not defined (yet) */
- if (cache->info[hash].name == 0)
- break;
- else if (!strcmp(name, cache->info[hash].name))
- break;
- }
- /* this assertion fails if the hash table is full */
- assert (i < size);
-
- return hash;
-}
-
-/** \brief Like strdup with error checking. */
-#define XSTRDUP(dest,source) do { \
- if (!(dest = strdup(source))) { \
- fprintf(stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); \
- abort(); \
- } \
- } while (0)
-
-/** \brief Check if a value is in info->range. */
-UNUSED static bool
-checkValue(const driOptionValue *v, const driOptionInfo *info)
-{
- switch (info->type) {
- case DRI_ENUM: /* enum is just a special integer */
- case DRI_INT:
- return (info->range.start._int == info->range.end._int ||
- (v->_int >= info->range.start._int &&
- v->_int <= info->range.end._int));
-
- case DRI_FLOAT:
- return (info->range.start._float == info->range.end._float ||
- (v->_float >= info->range.start._float &&
- v->_float <= info->range.end._float));
-
- default:
- return true;
- }
-}
-
-void
-driParseOptionInfo(driOptionCache *info,
- const driOptionDescription *configOptions,
- unsigned numOptions)
-{
- /* Make the hash table big enough to fit more than the maximum number of
- * config options we've ever seen in a driver.
- */
- info->tableSize = 6;
- info->info = calloc(1 << info->tableSize, sizeof(driOptionInfo));
- info->values = calloc(1 << info->tableSize, sizeof(driOptionValue));
- if (info->info == NULL || info->values == NULL) {
- fprintf(stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
- abort();
- }
-
- UNUSED bool in_section = false;
- for (int o = 0; o < numOptions; o++) {
- const driOptionDescription *opt = &configOptions[o];
-
- if (opt->info.type == DRI_SECTION) {
- in_section = true;
- continue;
- }
-
- /* for driconf xml generation, options must always be preceded by a
- * DRI_CONF_SECTION
- */
- assert(in_section);
-
- const char *name = opt->info.name;
- int i = findOption(info, name);
- driOptionInfo *optinfo = &info->info[i];
- driOptionValue *optval = &info->values[i];
-
- assert(!optinfo->name); /* No duplicate options in your list. */
-
- optinfo->type = opt->info.type;
- optinfo->range = opt->info.range;
- XSTRDUP(optinfo->name, name);
-
- switch (opt->info.type) {
- case DRI_BOOL:
- optval->_bool = opt->value._bool;
- break;
-
- case DRI_INT:
- case DRI_ENUM:
- optval->_int = opt->value._int;
- break;
-
- case DRI_FLOAT:
- optval->_float = opt->value._float;
- break;
-
- case DRI_STRING:
- XSTRDUP(optval->_string, opt->value._string);
- break;
-
- case DRI_SECTION:
- unreachable("handled above");
- }
-
- /* Built-in default values should always be valid. */
- assert(checkValue(optval, optinfo));
- }
-}
-
-char *
-driGetOptionsXml(const driOptionDescription *configOptions, unsigned numOptions)
-{
- char *str = ralloc_strdup(NULL,
- "\n" \
- "\n" \
- " \n" \
- " \n" \
- " \n" \
- " \n" \
- " \n" \
- " \n" \
- " \n" \
- "]>" \
- "\n");
-
- bool in_section = false;
- for (int o = 0; o < numOptions; o++) {
- const driOptionDescription *opt = &configOptions[o];
-
- const char *name = opt->info.name;
- const char *types[] = {
- [DRI_BOOL] = "bool",
- [DRI_INT] = "int",
- [DRI_FLOAT] = "float",
- [DRI_ENUM] = "enum",
- [DRI_STRING] = "string",
- };
-
- if (opt->info.type == DRI_SECTION) {
- if (in_section)
- ralloc_asprintf_append(&str, " \n");
-
- ralloc_asprintf_append(&str,
- " \n"
- " \n",
- opt->desc);
-
- in_section = true;
- continue;
- }
-
- ralloc_asprintf_append(&str,
- " \n");
- }
-
- assert(in_section);
- ralloc_asprintf_append(&str, " \n");
-
- ralloc_asprintf_append(&str, "\n");
-
- char *output = strdup(str);
- ralloc_free(str);
-
- return output;
-}
-
-#if WITH_XMLCONFIG
-
static bool
be_verbose(void)
{
@@ -327,102 +71,6 @@ be_verbose(void)
return strstr(s, "silent") == NULL;
}
-/**
- * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
- * is set.
- *
- * Is called from the drivers.
- *
- * \param f \c printf like format string.
- */
-static void
-__driUtilMessage(const char *f, ...)
-{
- va_list args;
- const char *libgl_debug;
-
- libgl_debug=getenv("LIBGL_DEBUG");
- if (libgl_debug && !strstr(libgl_debug, "quiet")) {
- fprintf(stderr, "libGL: ");
- va_start(args, f);
- vfprintf(stderr, f, args);
- va_end(args);
- fprintf(stderr, "\n");
- }
-}
-
-/** \brief Output a warning message. */
-#define XML_WARNING1(msg) do { \
- __driUtilMessage("Warning in %s line %d, column %d: "msg, data->name, \
- (int) XML_GetCurrentLineNumber(data->parser), \
- (int) XML_GetCurrentColumnNumber(data->parser)); \
- } while (0)
-#define XML_WARNING(msg, ...) do { \
- __driUtilMessage("Warning in %s line %d, column %d: "msg, data->name, \
- (int) XML_GetCurrentLineNumber(data->parser), \
- (int) XML_GetCurrentColumnNumber(data->parser), \
- ##__VA_ARGS__); \
- } while (0)
-/** \brief Output an error message. */
-#define XML_ERROR1(msg) do { \
- __driUtilMessage("Error in %s line %d, column %d: "msg, data->name, \
- (int) XML_GetCurrentLineNumber(data->parser), \
- (int) XML_GetCurrentColumnNumber(data->parser)); \
- } while (0)
-#define XML_ERROR(msg, ...) do { \
- __driUtilMessage("Error in %s line %d, column %d: "msg, data->name, \
- (int) XML_GetCurrentLineNumber(data->parser), \
- (int) XML_GetCurrentColumnNumber(data->parser), \
- ##__VA_ARGS__); \
- } while (0)
-
-/** \brief Parser context for configuration files. */
-struct OptConfData {
- const char *name;
- XML_Parser parser;
- driOptionCache *cache;
- int screenNum;
- const char *driverName, *execName;
- const char *kernelDriverName;
- const char *engineName;
- const char *applicationName;
- uint32_t engineVersion;
- uint32_t applicationVersion;
- uint32_t ignoringDevice;
- uint32_t ignoringApp;
- uint32_t inDriConf;
- uint32_t inDevice;
- uint32_t inApp;
- uint32_t inOption;
-};
-
-/** \brief Elements in configuration files. */
-enum OptConfElem {
- OC_APPLICATION = 0, OC_DEVICE, OC_DRICONF, OC_ENGINE, OC_OPTION, OC_COUNT
-};
-static const char *OptConfElems[] = {
- [OC_APPLICATION] = "application",
- [OC_DEVICE] = "device",
- [OC_DRICONF] = "driconf",
- [OC_ENGINE] = "engine",
- [OC_OPTION] = "option",
-};
-
-static int compare(const void *a, const void *b) {
- return strcmp(*(char *const*)a, *(char *const*)b);
-}
-/** \brief Binary search in a string array. */
-static uint32_t
-bsearchStr(const char *name, const char *elems[], uint32_t count)
-{
- const char **found;
- found = bsearch(&name, elems, count, sizeof(char *), compare);
- if (found)
- return found - elems;
- else
- return count;
-}
-
/** \brief Locale-independent integer parser.
*
* Works similar to strtol. Leading space is NOT skipped. The input
@@ -602,6 +250,376 @@ parseValue(driOptionValue *v, driOptionType type, const char *string)
return true;
}
+/** \brief Find an option in an option cache with the name as key */
+static uint32_t
+findOption(const driOptionCache *cache, const char *name)
+{
+ uint32_t len = strlen(name);
+ uint32_t size = 1 << cache->tableSize, mask = size - 1;
+ uint32_t hash = 0;
+ uint32_t i, shift;
+
+ /* compute a hash from the variable length name */
+ for (i = 0, shift = 0; i < len; ++i, shift = (shift+8) & 31)
+ hash += (uint32_t)name[i] << shift;
+ hash *= hash;
+ hash = (hash >> (16-cache->tableSize/2)) & mask;
+
+ /* this is just the starting point of the linear search for the option */
+ for (i = 0; i < size; ++i, hash = (hash+1) & mask) {
+ /* if we hit an empty entry then the option is not defined (yet) */
+ if (cache->info[hash].name == 0)
+ break;
+ else if (!strcmp(name, cache->info[hash].name))
+ break;
+ }
+ /* this assertion fails if the hash table is full */
+ assert (i < size);
+
+ return hash;
+}
+
+/** \brief Like strdup with error checking. */
+#define XSTRDUP(dest,source) do { \
+ if (!(dest = strdup(source))) { \
+ fprintf(stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); \
+ abort(); \
+ } \
+ } while (0)
+
+/** \brief Check if a value is in info->range. */
+UNUSED static bool
+checkValue(const driOptionValue *v, const driOptionInfo *info)
+{
+ switch (info->type) {
+ case DRI_ENUM: /* enum is just a special integer */
+ case DRI_INT:
+ return (info->range.start._int == info->range.end._int ||
+ (v->_int >= info->range.start._int &&
+ v->_int <= info->range.end._int));
+
+ case DRI_FLOAT:
+ return (info->range.start._float == info->range.end._float ||
+ (v->_float >= info->range.start._float &&
+ v->_float <= info->range.end._float));
+
+ default:
+ return true;
+ }
+}
+
+void
+driParseOptionInfo(driOptionCache *info,
+ const driOptionDescription *configOptions,
+ unsigned numOptions)
+{
+ /* Make the hash table big enough to fit more than the maximum number of
+ * config options we've ever seen in a driver.
+ */
+ info->tableSize = 6;
+ info->info = calloc(1 << info->tableSize, sizeof(driOptionInfo));
+ info->values = calloc(1 << info->tableSize, sizeof(driOptionValue));
+ if (info->info == NULL || info->values == NULL) {
+ fprintf(stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
+ abort();
+ }
+
+ UNUSED bool in_section = false;
+ for (int o = 0; o < numOptions; o++) {
+ const driOptionDescription *opt = &configOptions[o];
+
+ if (opt->info.type == DRI_SECTION) {
+ in_section = true;
+ continue;
+ }
+
+ /* for driconf xml generation, options must always be preceded by a
+ * DRI_CONF_SECTION
+ */
+ assert(in_section);
+
+ const char *name = opt->info.name;
+ int i = findOption(info, name);
+ driOptionInfo *optinfo = &info->info[i];
+ driOptionValue *optval = &info->values[i];
+
+ assert(!optinfo->name); /* No duplicate options in your list. */
+
+ optinfo->type = opt->info.type;
+ optinfo->range = opt->info.range;
+ XSTRDUP(optinfo->name, name);
+
+ switch (opt->info.type) {
+ case DRI_BOOL:
+ optval->_bool = opt->value._bool;
+ break;
+
+ case DRI_INT:
+ case DRI_ENUM:
+ optval->_int = opt->value._int;
+ break;
+
+ case DRI_FLOAT:
+ optval->_float = opt->value._float;
+ break;
+
+ case DRI_STRING:
+ XSTRDUP(optval->_string, opt->value._string);
+ break;
+
+ case DRI_SECTION:
+ unreachable("handled above");
+ }
+
+ /* Built-in default values should always be valid. */
+ assert(checkValue(optval, optinfo));
+
+ char *envVal = getenv(name);
+ if (envVal != NULL) {
+ driOptionValue v;
+ if (parseValue(&v, opt->info.type, envVal) &&
+ checkValue(&v, optinfo)) {
+ /* don't use XML_WARNING, we want the user to see this! */
+ if (be_verbose()) {
+ fprintf(stderr,
+ "ATTENTION: default value of option %s overridden by environment.\n",
+ name);
+ }
+ *optval = v;
+ } else {
+ fprintf(stderr, "illegal environment value for %s: \"%s\". Ignoring.\n",
+ name, envVal);
+ }
+ }
+ }
+}
+
+char *
+driGetOptionsXml(const driOptionDescription *configOptions, unsigned numOptions)
+{
+ char *str = ralloc_strdup(NULL,
+ "\n" \
+ "\n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ "]>" \
+ "\n");
+
+ bool in_section = false;
+ for (int o = 0; o < numOptions; o++) {
+ const driOptionDescription *opt = &configOptions[o];
+
+ const char *name = opt->info.name;
+ const char *types[] = {
+ [DRI_BOOL] = "bool",
+ [DRI_INT] = "int",
+ [DRI_FLOAT] = "float",
+ [DRI_ENUM] = "enum",
+ [DRI_STRING] = "string",
+ };
+
+ if (opt->info.type == DRI_SECTION) {
+ if (in_section)
+ ralloc_asprintf_append(&str, " \n");
+
+ ralloc_asprintf_append(&str,
+ " \n"
+ " \n",
+ opt->desc);
+
+ in_section = true;
+ continue;
+ }
+
+ ralloc_asprintf_append(&str,
+ " \n");
+ }
+
+ assert(in_section);
+ ralloc_asprintf_append(&str, " \n");
+
+ ralloc_asprintf_append(&str, "\n");
+
+ char *output = strdup(str);
+ ralloc_free(str);
+
+ return output;
+}
+
+#if WITH_XMLCONFIG
+
+/**
+ * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
+ * is set.
+ *
+ * Is called from the drivers.
+ *
+ * \param f \c printf like format string.
+ */
+static void
+__driUtilMessage(const char *f, ...)
+{
+ va_list args;
+ const char *libgl_debug;
+
+ libgl_debug=getenv("LIBGL_DEBUG");
+ if (libgl_debug && !strstr(libgl_debug, "quiet")) {
+ fprintf(stderr, "libGL: ");
+ va_start(args, f);
+ vfprintf(stderr, f, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+}
+
+/** \brief Output a warning message. */
+#define XML_WARNING1(msg) do { \
+ __driUtilMessage("Warning in %s line %d, column %d: "msg, data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser)); \
+ } while (0)
+#define XML_WARNING(msg, ...) do { \
+ __driUtilMessage("Warning in %s line %d, column %d: "msg, data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser), \
+ ##__VA_ARGS__); \
+ } while (0)
+/** \brief Output an error message. */
+#define XML_ERROR1(msg) do { \
+ __driUtilMessage("Error in %s line %d, column %d: "msg, data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser)); \
+ } while (0)
+#define XML_ERROR(msg, ...) do { \
+ __driUtilMessage("Error in %s line %d, column %d: "msg, data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser), \
+ ##__VA_ARGS__); \
+ } while (0)
+
+/** \brief Parser context for configuration files. */
+struct OptConfData {
+ const char *name;
+ XML_Parser parser;
+ driOptionCache *cache;
+ int screenNum;
+ const char *driverName, *execName;
+ const char *kernelDriverName;
+ const char *engineName;
+ const char *applicationName;
+ uint32_t engineVersion;
+ uint32_t applicationVersion;
+ uint32_t ignoringDevice;
+ uint32_t ignoringApp;
+ uint32_t inDriConf;
+ uint32_t inDevice;
+ uint32_t inApp;
+ uint32_t inOption;
+};
+
+/** \brief Elements in configuration files. */
+enum OptConfElem {
+ OC_APPLICATION = 0, OC_DEVICE, OC_DRICONF, OC_ENGINE, OC_OPTION, OC_COUNT
+};
+static const char *OptConfElems[] = {
+ [OC_APPLICATION] = "application",
+ [OC_DEVICE] = "device",
+ [OC_DRICONF] = "driconf",
+ [OC_ENGINE] = "engine",
+ [OC_OPTION] = "option",
+};
+
+static int compare(const void *a, const void *b) {
+ return strcmp(*(char *const*)a, *(char *const*)b);
+}
+/** \brief Binary search in a string array. */
+static uint32_t
+bsearchStr(const char *name, const char *elems[], uint32_t count)
+{
+ const char **found;
+ found = bsearch(&name, elems, count, sizeof(char *), compare);
+ if (found)
+ return found - elems;
+ else
+ return count;
+}
+
/** \brief Parse a list of ranges of type info->type. */
static unsigned char
parseRange(driOptionInfo *info, const char *string)