i965/nir/vec4: Implement vector "any" operation
[mesa.git] / src / mesa / drivers / dri / common / xmlconfig.c
index 738b1ae97fd374d0caeeb2196becc861245d0dad..f17693e739ff0417f0e9c5a2f1ca4e953a5031e9 100644 (file)
  * \author Felix Kuehling
  */
 
-#include "main/glheader.h"
-
+#include <stdarg.h>
+#include <stdio.h>
 #include <string.h>
 #include <assert.h>
 #include <expat.h>
 #include <fcntl.h>
+#include <math.h>
 #include <unistd.h>
 #include <errno.h>
 #include "main/imports.h"
 extern char *program_invocation_name, *program_invocation_short_name;
 #    endif
 #    define GET_PROGRAM_NAME() program_invocation_short_name
+#elif defined(__CYGWIN__)
+#    define GET_PROGRAM_NAME() program_invocation_short_name
 #elif defined(__FreeBSD__) && (__FreeBSD__ >= 2)
 #    include <osreldate.h>
 #    if (__FreeBSD_version >= 440000)
 #        include <stdlib.h>
 #        define GET_PROGRAM_NAME() getprogname()
 #    endif
-#elif defined(__NetBSD__) && defined(__NetBSD_Version) && (__NetBSD_Version >= 106000100)
+#elif defined(__NetBSD__) && defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 106000100)
+#    include <stdlib.h>
+#    define GET_PROGRAM_NAME() getprogname()
+#elif defined(__APPLE__)
 #    include <stdlib.h>
 #    define GET_PROGRAM_NAME() getprogname()
 #elif defined(__sun)
@@ -61,11 +67,29 @@ extern char *program_invocation_name, *program_invocation_short_name;
    the basename to match BSD getprogname() */
 #    include <stdlib.h>
 #    include <libgen.h>
-#    define GET_PROGRAM_NAME() basename(getexecname())
+
+static const char *__getProgramName () {
+    static const char *progname;
+
+    if (progname == NULL) {
+       const char *e = getexecname();
+       if (e != NULL) {
+           /* Have to make a copy since getexecname can return a readonly
+              string, but basename expects to be able to modify its arg. */
+           char *n = strdup(e);
+           if (n != NULL) {
+               progname = basename(n);
+           }
+       }
+    }
+    return progname;
+}
+
+#    define GET_PROGRAM_NAME() __getProgramName()
 #endif
 
 #if !defined(GET_PROGRAM_NAME)
-#    if defined(__OpenBSD__) || defined(NetBSD) || defined(__UCLIBC__)
+#    if defined(__OpenBSD__) || defined(NetBSD) || defined(__UCLIBC__) || defined(ANDROID)
 /* This is a hack. It's said to work on OpenBSD, NetBSD and GNU.
  * Rogelio M.Serrano Jr. reported it's also working with UCLIBC. It's
  * used as a last resort, if there is no documented facility available. */
@@ -85,15 +109,15 @@ static const char *__getProgramName () {
 #endif
 
 /** \brief Find an option in an option cache with the name as key */
-static GLuint findOption (const driOptionCache *cache, const char *name) {
-    GLuint len = strlen (name);
-    GLuint size = 1 << cache->tableSize, mask = size - 1;
-    GLuint hash = 0;
-    GLuint i, shift;
+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 += (GLuint)name[i] << shift;
+       hash += (uint32_t)name[i] << shift;
     hash *= hash;
     hash = (hash >> (16-cache->tableSize/2)) & mask;
 
@@ -111,20 +135,10 @@ static GLuint findOption (const driOptionCache *cache, const char *name) {
     return hash;
 }
 
-/** \brief Count the real number of options in an option cache */
-static GLuint countOptions (const driOptionCache *cache) {
-    GLuint size = 1 << cache->tableSize;
-    GLuint i, count = 0;
-    for (i = 0; i < size; ++i)
-       if (cache->info[i].name)
-           count++;
-    return count;
-}
-
-/** \brief Like strdup but using MALLOC and with error checking. */
+/** \brief Like strdup but using malloc and with error checking. */
 #define XSTRDUP(dest,source) do { \
-    GLuint len = strlen (source); \
-    if (!(dest = MALLOC (len+1))) { \
+    uint32_t len = strlen (source); \
+    if (!(dest = malloc(len+1))) { \
        fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); \
        abort(); \
     } \
@@ -135,8 +149,8 @@ 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 GLuint bsearchStr (const XML_Char *name,
-                         const XML_Char *elems[], GLuint count) {
+static uint32_t bsearchStr (const XML_Char *name,
+                         const XML_Char *elems[], uint32_t count) {
     const XML_Char **found;
     found = bsearch (&name, elems, count, sizeof (XML_Char *), compare);
     if (found)
@@ -154,11 +168,11 @@ static GLuint bsearchStr (const XML_Char *name,
  * returning tail points to the first character that is not part of
  * the integer number. If no number was found then tail points to the
  * start of the input string. */
-static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) {
-    GLint radix = base == 0 ? 10 : base;
-    GLint result = 0;
-    GLint sign = 1;
-    GLboolean numberFound = GL_FALSE;
+static int strToI (const XML_Char *string, const XML_Char **tail, int base) {
+    int radix = base == 0 ? 10 : base;
+    int result = 0;
+    int sign = 1;
+    bool numberFound = false;
     const XML_Char *start = string;
 
     assert (radix >= 2 && radix <= 36);
@@ -169,7 +183,7 @@ static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) {
     } else if (*string == '+')
        string++;
     if (base == 0 && *string == '0') {
-       numberFound = GL_TRUE; 
+       numberFound = true;
        if (*(string+1) == 'x' || *(string+1) == 'X') {
            radix = 16;
            string += 2;
@@ -179,7 +193,7 @@ static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) {
        }
     }
     do {
-       GLint digit = -1;
+       int digit = -1;
        if (radix <= 10) {
            if (*string >= '0' && *string < '0' + radix)
                digit = *string - '0';
@@ -192,12 +206,12 @@ static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) {
                digit = *string - 'A' + 10;
        }
        if (digit != -1) {
-           numberFound = GL_TRUE;
+           numberFound = true;
            result = radix*result + digit;
            string++;
        } else
            break;
-    } while (GL_TRUE);
+    } while (true);
     *tail = numberFound ? string : start;
     return sign * result;
 }
@@ -206,7 +220,7 @@ static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) {
  *
  * Works similar to strtod. Leading space is NOT skipped. The input
  * number may have an optional sign. '.' is interpreted as decimal
- * point and may occor at most once. Optionally the number may end in
+ * point and may occur at most once. Optionally the number may end in
  * [eE]<exponent>, where <exponent> is an integer as recognized by
  * strToI. In that case the result is number * 10^exponent. After
  * returning tail points to the first character that is not part of
@@ -214,9 +228,9 @@ static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) {
  * to the start of the input string.
  *
  * Uses two passes for maximum accuracy. */
-static GLfloat strToF (const XML_Char *string, const XML_Char **tail) {
-    GLint nDigits = 0, pointPos, exponent;
-    GLfloat sign = 1.0f, result = 0.0f, scale;
+static float strToF (const XML_Char *string, const XML_Char **tail) {
+    int nDigits = 0, pointPos, exponent;
+    float sign = 1.0f, result = 0.0f, scale;
     const XML_Char *start = string, *numStart;
 
     /* sign */
@@ -259,13 +273,13 @@ static GLfloat strToF (const XML_Char *string, const XML_Char **tail) {
     string = numStart;
 
     /* scale of the first digit */
-    scale = sign * (GLfloat)pow (10.0, (GLdouble)(pointPos-1 + exponent));
+    scale = sign * (float)pow (10.0, (double)(pointPos-1 + exponent));
 
     /* second pass: parse digits */
     do {
        if (*string != '.') {
            assert (*string >= '0' && *string <= '9');
-           result += scale * (GLfloat)(*string - '0');
+           result += scale * (float)(*string - '0');
            scale *= 0.1f;
            nDigits--;
        }
@@ -276,7 +290,7 @@ static GLfloat strToF (const XML_Char *string, const XML_Char **tail) {
 }
 
 /** \brief Parse a value of a given type. */
-static GLboolean parseValue (driOptionValue *v, driOptionType type,
+static unsigned char parseValue (driOptionValue *v, driOptionType type,
                             const XML_Char *string) {
     const XML_Char *tail = NULL;
   /* skip leading white-space */
@@ -284,14 +298,14 @@ static GLboolean parseValue (driOptionValue *v, driOptionType type,
     switch (type) {
       case DRI_BOOL:
        if (!strcmp (string, "false")) {
-           v->_bool = GL_FALSE;
+           v->_bool = false;
            tail = string + 5;
        } else if (!strcmp (string, "true")) {
-           v->_bool = GL_TRUE;
+           v->_bool = true;
            tail = string + 4;
        }
        else
-           return GL_FALSE;
+           return false;
        break;
       case DRI_ENUM: /* enum is just a special integer */
       case DRI_INT:
@@ -300,23 +314,27 @@ static GLboolean parseValue (driOptionValue *v, driOptionType type,
       case DRI_FLOAT:
        v->_float = strToF (string, &tail);
        break;
+      case DRI_STRING:
+       free (v->_string);
+       v->_string = strndup(string, STRING_CONF_MAXLEN);
+       return GL_TRUE;
     }
 
     if (tail == string)
-       return GL_FALSE; /* empty string (or containing only white-space) */
+       return false; /* empty string (or containing only white-space) */
   /* skip trailing white space */
     if (*tail)
        tail += strspn (tail, " \f\n\r\t\v");
     if (*tail)
-       return GL_FALSE; /* something left over that is not part of value */
+       return false; /* something left over that is not part of value */
 
-    return GL_TRUE;
+    return true;
 }
 
 /** \brief Parse a list of ranges of type info->type. */
-static GLboolean parseRanges (driOptionInfo *info, const XML_Char *string) {
+static unsigned char parseRanges (driOptionInfo *info, const XML_Char *string) {
     XML_Char *cp, *range;
-    GLuint nRanges, i;
+    uint32_t nRanges, i;
     driOptionRange *ranges;
 
     XSTRDUP (cp, string);
@@ -326,7 +344,7 @@ static GLboolean parseRanges (driOptionInfo *info, const XML_Char *string) {
        if (*range == ',')
            ++nRanges;
 
-    if ((ranges = MALLOC (nRanges*sizeof(driOptionRange))) == NULL) {
+    if ((ranges = malloc(nRanges*sizeof(driOptionRange))) == NULL) {
        fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
        abort();
     }
@@ -361,42 +379,68 @@ static GLboolean parseRanges (driOptionInfo *info, const XML_Char *string) {
        else
            range = NULL;
     }
-    FREE (cp);
+    free(cp);
     if (i < nRanges) {
-       FREE (ranges);
-       return GL_FALSE;
+       free(ranges);
+       return false;
     } else
        assert (range == NULL);
 
     info->nRanges = nRanges;
     info->ranges = ranges;
-    return GL_TRUE;
+    return true;
 }
 
 /** \brief Check if a value is in one of info->ranges. */
-static GLboolean checkValue (const driOptionValue *v, const driOptionInfo *info) {
-    GLuint i;
+static bool checkValue (const driOptionValue *v, const driOptionInfo *info) {
+    uint32_t i;
     assert (info->type != DRI_BOOL); /* should be caught by the parser */
     if (info->nRanges == 0)
-       return GL_TRUE;
+       return true;
     switch (info->type) {
       case DRI_ENUM: /* enum is just a special integer */
       case DRI_INT:
        for (i = 0; i < info->nRanges; ++i)
            if (v->_int >= info->ranges[i].start._int &&
                v->_int <= info->ranges[i].end._int)
-               return GL_TRUE;
+               return true;
        break;
       case DRI_FLOAT:
        for (i = 0; i < info->nRanges; ++i)
            if (v->_float >= info->ranges[i].start._float &&
                v->_float <= info->ranges[i].end._float)
-               return GL_TRUE;
+               return true;
+       break;
+      case DRI_STRING:
        break;
       default:
        assert (0); /* should never happen */
     }
-    return GL_FALSE;
+    return false;
+}
+
+/**
+ * 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. */
@@ -445,11 +489,11 @@ struct OptInfoData {
     const char *name;
     XML_Parser parser;
     driOptionCache *cache;
-    GLboolean inDriInfo;
-    GLboolean inSection;
-    GLboolean inDesc;
-    GLboolean inOption;
-    GLboolean inEnum;
+    bool inDriInfo;
+    bool inSection;
+    bool inDesc;
+    bool inOption;
+    bool inEnum;
     int curOption;
 };
 
@@ -467,10 +511,10 @@ static const XML_Char *OptInfoElems[] = {
  * for external configuration tools.
  */
 static void parseEnumAttr (struct OptInfoData *data, const XML_Char **attr) {
-    GLuint i;
+    uint32_t i;
     const XML_Char *value = NULL, *text = NULL;
     driOptionValue v;
-    GLuint opt = data->curOption;
+    uint32_t opt = data->curOption;
     for (i = 0; attr[i]; i += 2) {
        if (!strcmp (attr[i], "value")) value = attr[i+1];
        else if (!strcmp (attr[i], "text")) text = attr[i+1];
@@ -490,7 +534,7 @@ static void parseEnumAttr (struct OptInfoData *data, const XML_Char **attr) {
  * for external configuration tools.
  */
 static void parseDescAttr (struct OptInfoData *data, const XML_Char **attr) {
-    GLuint i;
+    uint32_t i;
     const XML_Char *lang = NULL, *text = NULL;
     for (i = 0; attr[i]; i += 2) {
        if (!strcmp (attr[i], "lang")) lang = attr[i+1];
@@ -508,9 +552,9 @@ static void parseOptInfoAttr (struct OptInfoData *data, const XML_Char **attr) {
     const XML_Char *attrVal[OA_COUNT] = {NULL, NULL, NULL, NULL};
     const char *defaultVal;
     driOptionCache *cache = data->cache;
-    GLuint opt, i;
+    uint32_t opt, i;
     for (i = 0; attr[i]; i += 2) {
-       GLuint attrName = bsearchStr (attr[i], optAttr, OA_COUNT);
+       uint32_t attrName = bsearchStr (attr[i], optAttr, OA_COUNT);
        if (attrName >= OA_COUNT)
            XML_FATAL ("illegal option attribute: %s", attr[i]);
        attrVal[attrName] = attr[i+1];
@@ -534,6 +578,8 @@ static void parseOptInfoAttr (struct OptInfoData *data, const XML_Char **attr) {
        cache->info[opt].type = DRI_INT;
     else if (!strcmp (attrVal[OA_TYPE], "float"))
        cache->info[opt].type = DRI_FLOAT;
+    else if (!strcmp (attrVal[OA_TYPE], "string"))
+       cache->info[opt].type = DRI_STRING;
     else
        XML_FATAL ("illegal type in option: %s.", attrVal[OA_TYPE]);
 
@@ -546,7 +592,7 @@ static void parseOptInfoAttr (struct OptInfoData *data, const XML_Char **attr) {
     } else
        defaultVal = attrVal[OA_DEFAULT];
     if (!parseValue (&cache->values[opt], cache->info[opt].type, defaultVal))
-       XML_FATAL ("illegal default value: %s.", defaultVal);
+       XML_FATAL ("illegal default value for %s: %s.", cache->info[opt].name, defaultVal);
 
     if (attrVal[OA_VALID]) {
        if (cache->info[opt].type == DRI_BOOL)
@@ -575,7 +621,7 @@ static void optInfoStartElem (void *userData, const XML_Char *name,
            XML_FATAL1 ("nested <driinfo> elements.");
        if (attr[0])
            XML_FATAL1 ("attributes specified on <driinfo> element.");
-       data->inDriInfo = GL_TRUE;
+       data->inDriInfo = true;
        break;
       case OI_SECTION:
        if (!data->inDriInfo)
@@ -584,14 +630,14 @@ static void optInfoStartElem (void *userData, const XML_Char *name,
            XML_FATAL1 ("nested <section> elements.");
        if (attr[0])
            XML_FATAL1 ("attributes specified on <section> element.");
-       data->inSection = GL_TRUE;
+       data->inSection = true;
        break;
       case OI_DESCRIPTION:
        if (!data->inSection && !data->inOption)
            XML_FATAL1 ("<description> must be inside <description> or <option.");
        if (data->inDesc)
            XML_FATAL1 ("nested <description> elements.");
-       data->inDesc = GL_TRUE;
+       data->inDesc = true;
        parseDescAttr (data, attr);
        break;
       case OI_OPTION:
@@ -601,7 +647,7 @@ static void optInfoStartElem (void *userData, const XML_Char *name,
            XML_FATAL1 ("<option> nested in <description> element.");
        if (data->inOption)
            XML_FATAL1 ("nested <option> elements.");
-       data->inOption = GL_TRUE;
+       data->inOption = true;
        parseOptInfoAttr (data, attr);
        break;
       case OI_ENUM:
@@ -609,7 +655,7 @@ static void optInfoStartElem (void *userData, const XML_Char *name,
            XML_FATAL1 ("<enum> must be inside <option> and <description>.");
        if (data->inEnum)
            XML_FATAL1 ("nested <enum> elements.");
-       data->inEnum = GL_TRUE;
+       data->inEnum = true;
        parseEnumAttr (data, attr);
        break;
       default:
@@ -623,44 +669,37 @@ static void optInfoEndElem (void *userData, const XML_Char *name) {
     enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT);
     switch (elem) {
       case OI_DRIINFO:
-       data->inDriInfo = GL_FALSE;
+       data->inDriInfo = false;
        break;
       case OI_SECTION:
-       data->inSection = GL_FALSE;
+       data->inSection = false;
        break;
       case OI_DESCRIPTION:
-       data->inDesc = GL_FALSE;
+       data->inDesc = false;
        break;
       case OI_OPTION:
-       data->inOption = GL_FALSE;
+       data->inOption = false;
        break;
       case OI_ENUM:
-       data->inEnum = GL_FALSE;
+       data->inEnum = false;
        break;
       default:
        assert (0); /* should have been caught by StartElem */
     }
 }
 
-void driParseOptionInfo (driOptionCache *info,
-                        const char *configOptions, GLuint nConfigOptions) {
+void driParseOptionInfo (driOptionCache *info, const char *configOptions) {
     XML_Parser p;
     int status;
     struct OptInfoData userData;
     struct OptInfoData *data = &userData;
-    GLuint realNoptions;
-
-  /* determine hash table size and allocate memory:
-   * 3/2 of the number of options, rounded up, so there remains always
-   * at least one free entry. This is needed for detecting undefined
-   * options in configuration files without getting a hash table overflow.
-   * Round this up to a power of two. */
-    GLuint minSize = (nConfigOptions*3 + 1) / 2;
-    GLuint size, log2size;
-    for (size = 1, log2size = 0; size < minSize; size <<= 1, ++log2size);
-    info->tableSize = log2size;
-    info->info = CALLOC (size * sizeof (driOptionInfo));
-    info->values = CALLOC (size * sizeof (driOptionValue));
+
+    /* 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();
@@ -673,11 +712,11 @@ void driParseOptionInfo (driOptionCache *info,
     userData.name = "__driConfigOptions";
     userData.parser = p;
     userData.cache = info;
-    userData.inDriInfo = GL_FALSE;
-    userData.inSection = GL_FALSE;
-    userData.inDesc = GL_FALSE;
-    userData.inOption = GL_FALSE;
-    userData.inEnum = GL_FALSE;
+    userData.inDriInfo = false;
+    userData.inSection = false;
+    userData.inDesc = false;
+    userData.inOption = false;
+    userData.inEnum = false;
     userData.curOption = -1;
 
     status = XML_Parse (p, configOptions, strlen (configOptions), 1);
@@ -685,17 +724,6 @@ void driParseOptionInfo (driOptionCache *info,
        XML_FATAL ("%s.", XML_ErrorString(XML_GetErrorCode(p)));
 
     XML_ParserFree (p);
-
-  /* Check if the actual number of options matches nConfigOptions.
-   * A mismatch is not fatal (a hash table overflow would be) but we
-   * want the driver developer's attention anyway. */
-    realNoptions = countOptions (info);
-    if (realNoptions != nConfigOptions) {
-       fprintf (stderr,
-                "Error: nConfigOptions (%u) does not match the actual number of options in\n"
-                "       __driConfigOptions (%u).\n",
-                nConfigOptions, realNoptions);
-    }
 }
 
 /** \brief Parser context for configuration files. */
@@ -703,14 +731,14 @@ struct OptConfData {
     const char *name;
     XML_Parser parser;
     driOptionCache *cache;
-    GLint screenNum;
+    int screenNum;
     const char *driverName, *execName;
-    GLuint ignoringDevice;
-    GLuint ignoringApp;
-    GLuint inDriConf;
-    GLuint inDevice;
-    GLuint inApp;
-    GLuint inOption;
+    uint32_t ignoringDevice;
+    uint32_t ignoringApp;
+    uint32_t inDriConf;
+    uint32_t inDevice;
+    uint32_t inApp;
+    uint32_t inOption;
 };
 
 /** \brief Elements in configuration files. */
@@ -723,12 +751,12 @@ static const XML_Char *OptConfElems[] = {
 
 /** \brief Parse attributes of a device element. */
 static void parseDeviceAttr (struct OptConfData *data, const XML_Char **attr) {
-    GLuint i;
+    uint32_t i;
     const XML_Char *driver = NULL, *screen = NULL;
     for (i = 0; attr[i]; i += 2) {
        if (!strcmp (attr[i], "driver")) driver = attr[i+1];
        else if (!strcmp (attr[i], "screen")) screen = attr[i+1];
-       else XML_WARNING("unkown device attribute: %s.", attr[i]);
+       else XML_WARNING("unknown device attribute: %s.", attr[i]);
     }
     if (driver && strcmp (driver, data->driverName))
        data->ignoringDevice = data->inDevice;
@@ -743,12 +771,12 @@ static void parseDeviceAttr (struct OptConfData *data, const XML_Char **attr) {
 
 /** \brief Parse attributes of an application element. */
 static void parseAppAttr (struct OptConfData *data, const XML_Char **attr) {
-    GLuint i;
-    const XML_Char *name = NULL, *exec = NULL;
+    uint32_t i;
+    const XML_Char *exec = NULL;
     for (i = 0; attr[i]; i += 2) {
-       if (!strcmp (attr[i], "name")) name = attr[i+1];
+       if (!strcmp (attr[i], "name")) /* not needed here */;
        else if (!strcmp (attr[i], "executable")) exec = attr[i+1];
-       else XML_WARNING("unkown application attribute: %s.", attr[i]);
+       else XML_WARNING("unknown application attribute: %s.", attr[i]);
     }
     if (exec && strcmp (exec, data->execName))
        data->ignoringApp = data->inApp;
@@ -756,20 +784,22 @@ static void parseAppAttr (struct OptConfData *data, const XML_Char **attr) {
 
 /** \brief Parse attributes of an option element. */
 static void parseOptConfAttr (struct OptConfData *data, const XML_Char **attr) {
-    GLuint i;
+    uint32_t i;
     const XML_Char *name = NULL, *value = NULL;
     for (i = 0; attr[i]; i += 2) {
        if (!strcmp (attr[i], "name")) name = attr[i+1];
        else if (!strcmp (attr[i], "value")) value = attr[i+1];
-       else XML_WARNING("unkown option attribute: %s.", attr[i]);
+       else XML_WARNING("unknown option attribute: %s.", attr[i]);
     }
     if (!name) XML_WARNING1 ("name attribute missing in option.");
     if (!value) XML_WARNING1 ("value attribute missing in option.");
     if (name && value) {
        driOptionCache *cache = data->cache;
-       GLuint opt = findOption (cache, name);
+       uint32_t opt = findOption (cache, name);
        if (cache->info[opt].name == NULL)
-           XML_WARNING ("undefined option: %s.", name);
+            /* don't use XML_WARNING, drirc defines options for all drivers,
+             * but not all drivers support them */
+            return;
        else if (getenv (cache->info[opt].name))
          /* don't use XML_WARNING, we want the user to see this! */
            fprintf (stderr, "ATTENTION: option value of option %s ignored.\n",
@@ -850,15 +880,20 @@ static void optConfEndElem (void *userData, const XML_Char *name) {
 
 /** \brief Initialize an option cache based on info */
 static void initOptionCache (driOptionCache *cache, const driOptionCache *info) {
+    GLuint i, size = 1 << info->tableSize;
     cache->info = info->info;
     cache->tableSize = info->tableSize;
-    cache->values = MALLOC ((1<<info->tableSize) * sizeof (driOptionValue));
+    cache->values = malloc((1<<info->tableSize) * sizeof (driOptionValue));
     if (cache->values == NULL) {
        fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
        abort();
     }
     memcpy (cache->values, info->values,
            (1<<info->tableSize) * sizeof (driOptionValue));
+    for (i = 0; i < size; ++i) {
+       if (cache->info[i].type == DRI_STRING)
+           XSTRDUP(cache->values[i]._string, info->values[i]._string);
+    }
 }
 
 /** \brief Parse the named configuration file */
@@ -901,10 +936,10 @@ static void parseOneConfigFile (XML_Parser p) {
 }
 
 void driParseConfigFiles (driOptionCache *cache, const driOptionCache *info,
-                         GLint screenNum, const char *driverName) {
+                         int screenNum, const char *driverName) {
     char *filenames[2] = {"/etc/drirc", NULL};
     char *home;
-    GLuint i;
+    uint32_t i;
     struct OptConfData userData;
 
     initOptionCache (cache, info);
@@ -915,8 +950,8 @@ void driParseConfigFiles (driOptionCache *cache, const driOptionCache *info,
     userData.execName = GET_PROGRAM_NAME();
 
     if ((home = getenv ("HOME"))) {
-       GLuint len = strlen (home);
-       filenames[1] = MALLOC (len + 7+1);
+       uint32_t len = strlen (home);
+       filenames[1] = malloc(len + 7+1);
        if (filenames[1] == NULL)
            __driUtilMessage ("Can't allocate memory for %s/.drirc.", home);
        else {
@@ -946,56 +981,68 @@ void driParseConfigFiles (driOptionCache *cache, const driOptionCache *info,
        XML_ParserFree (p);
     }
 
-    if (filenames[1])
-       FREE (filenames[1]);
+    free(filenames[1]);
 }
 
 void driDestroyOptionInfo (driOptionCache *info) {
     driDestroyOptionCache (info);
     if (info->info) {
-       GLuint i, size = 1 << info->tableSize;
+       uint32_t i, size = 1 << info->tableSize;
        for (i = 0; i < size; ++i) {
            if (info->info[i].name) {
-               FREE (info->info[i].name);
-               if (info->info[i].ranges)
-                   FREE (info->info[i].ranges);
+               free(info->info[i].name);
+               free(info->info[i].ranges);
            }
        }
-       FREE (info->info);
+       free(info->info);
     }
 }
 
 void driDestroyOptionCache (driOptionCache *cache) {
-    if (cache->values)
-       FREE (cache->values);
+    if (cache->info) {
+       GLuint i, size = 1 << cache->tableSize;
+       for (i = 0; i < size; ++i) {
+           if (cache->info[i].type == DRI_STRING)
+               free(cache->values[i]._string);
+       }
+    }
+    free(cache->values);
 }
 
-GLboolean driCheckOption (const driOptionCache *cache, const char *name,
+unsigned char driCheckOption (const driOptionCache *cache, const char *name,
                          driOptionType type) {
-    GLuint i = findOption (cache, name);
+    uint32_t i = findOption (cache, name);
     return cache->info[i].name != NULL && cache->info[i].type == type;
 }
 
-GLboolean driQueryOptionb (const driOptionCache *cache, const char *name) {
-    GLuint i = findOption (cache, name);
+unsigned char driQueryOptionb (const driOptionCache *cache, const char *name) {
+    uint32_t i = findOption (cache, name);
   /* make sure the option is defined and has the correct type */
     assert (cache->info[i].name != NULL);
     assert (cache->info[i].type == DRI_BOOL);
     return cache->values[i]._bool;
 }
 
-GLint driQueryOptioni (const driOptionCache *cache, const char *name) {
-    GLuint i = findOption (cache, name);
+int driQueryOptioni (const driOptionCache *cache, const char *name) {
+    uint32_t i = findOption (cache, name);
   /* make sure the option is defined and has the correct type */
     assert (cache->info[i].name != NULL);
     assert (cache->info[i].type == DRI_INT || cache->info[i].type == DRI_ENUM);
     return cache->values[i]._int;
 }
 
-GLfloat driQueryOptionf (const driOptionCache *cache, const char *name) {
-    GLuint i = findOption (cache, name);
+float driQueryOptionf (const driOptionCache *cache, const char *name) {
+    uint32_t i = findOption (cache, name);
   /* make sure the option is defined and has the correct type */
     assert (cache->info[i].name != NULL);
     assert (cache->info[i].type == DRI_FLOAT);
     return cache->values[i]._float;
 }
+
+char *driQueryOptionstr (const driOptionCache *cache, const char *name) {
+    GLuint i = findOption (cache, name);
+  /* make sure the option is defined and has the correct type */
+    assert (cache->info[i].name != NULL);
+    assert (cache->info[i].type == DRI_STRING);
+    return cache->values[i]._string;
+}