1bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/* 2bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * XML DRI client-side driver configuration 3bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * Copyright (C) 2003 Felix Kuehling 4bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * 5bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * Permission is hereby granted, free of charge, to any person obtaining a 6bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * copy of this software and associated documentation files (the "Software"), 7bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * to deal in the Software without restriction, including without limitation 8bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * and/or sell copies of the Software, and to permit persons to whom the 10bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * Software is furnished to do so, subject to the following conditions: 11bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * 12bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * The above copyright notice and this permission notice shall be included 13bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * in all copies or substantial portions of the Software. 14bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * 15bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 19bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 21bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * 23bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl */ 24bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** 25bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * \file xmlconfig.c 26bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * \brief Driver-independent client-side part of the XML configuration 27bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * \author Felix Kuehling 28bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl */ 29bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 30ecadb51bbcb972a79f3ed79e65a7986b9396e757Brian Paul#include "main/glheader.h" 31bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 32bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#include <string.h> 33bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#include <assert.h> 34bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#include <expat.h> 35bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#include <fcntl.h> 36bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#include <unistd.h> 37bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#include <errno.h> 38ecadb51bbcb972a79f3ed79e65a7986b9396e757Brian Paul#include "main/imports.h" 39631a1a9ac8b97dec172205e13e33ef51f28bb1c0George Sapountzis#include "utils.h" 40bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#include "xmlconfig.h" 41bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 42bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#undef GET_PROGRAM_NAME 43bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 44486e5c26dc3164493b4f045b533fc1b9e1847581Felix Kuehling#if (defined(__GNU_LIBRARY__) || defined(__GLIBC__)) && !defined(__UCLIBC__) 4522ae633d1ea636e0e07ba044a0f8fa2195c83bc6Alan Hourihane# if !defined(__GLIBC__) || (__GLIBC__ < 2) 4622ae633d1ea636e0e07ba044a0f8fa2195c83bc6Alan Hourihane/* These aren't declared in any libc5 header */ 4722ae633d1ea636e0e07ba044a0f8fa2195c83bc6Alan Hourihaneextern char *program_invocation_name, *program_invocation_short_name; 4822ae633d1ea636e0e07ba044a0f8fa2195c83bc6Alan Hourihane# endif 49bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl# define GET_PROGRAM_NAME() program_invocation_short_name 50bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#elif defined(__FreeBSD__) && (__FreeBSD__ >= 2) 51bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl# include <osreldate.h> 52bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl# if (__FreeBSD_version >= 440000) 53bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl# include <stdlib.h> 54bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl# define GET_PROGRAM_NAME() getprogname() 55bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl# endif 56bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#elif defined(__NetBSD__) && defined(__NetBSD_Version) && (__NetBSD_Version >= 106000100) 57bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl# include <stdlib.h> 58bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl# define GET_PROGRAM_NAME() getprogname() 5979d56577700a4f4b8628b3b61098763d019f17d4Vinson Lee#elif defined(__APPLE__) 6079d56577700a4f4b8628b3b61098763d019f17d4Vinson Lee# include <stdlib.h> 6179d56577700a4f4b8628b3b61098763d019f17d4Vinson Lee# define GET_PROGRAM_NAME() getprogname() 62e1f9adc27445ea3381af1f71cfec0317298be5b1Alan Coopersmith#elif defined(__sun) 63e1f9adc27445ea3381af1f71cfec0317298be5b1Alan Coopersmith/* Solaris has getexecname() which returns the full path - return just 64e1f9adc27445ea3381af1f71cfec0317298be5b1Alan Coopersmith the basename to match BSD getprogname() */ 65e1f9adc27445ea3381af1f71cfec0317298be5b1Alan Coopersmith# include <stdlib.h> 66e1f9adc27445ea3381af1f71cfec0317298be5b1Alan Coopersmith# include <libgen.h> 6764ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith 6864ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmithstatic const char *__getProgramName () { 6964ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith static const char *progname; 7064ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith 7164ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith if (progname == NULL) { 7264ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith const char *e = getexecname(); 7364ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith if (e != NULL) { 7464ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith /* Have to make a copy since getexecname can return a readonly 7564ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith string, but basename expects to be able to modify its arg. */ 7664ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith char *n = strdup(e); 7764ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith if (n != NULL) { 7864ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith progname = basename(n); 7964ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith } 8064ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith } 8164ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith } 8264ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith return progname; 8364ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith} 8464ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith 8564ce3933f59f71ac78d83b8b3db813b6d2619382Alan Coopersmith# define GET_PROGRAM_NAME() __getProgramName() 86bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#endif 87bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 88bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#if !defined(GET_PROGRAM_NAME) 898cffec495c73f104819deab2bc5631abc1b36429Tapani Pälli# if defined(__OpenBSD__) || defined(NetBSD) || defined(__UCLIBC__) || defined(ANDROID) 90486e5c26dc3164493b4f045b533fc1b9e1847581Felix Kuehling/* This is a hack. It's said to work on OpenBSD, NetBSD and GNU. 91486e5c26dc3164493b4f045b533fc1b9e1847581Felix Kuehling * Rogelio M.Serrano Jr. reported it's also working with UCLIBC. It's 92bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * used as a last resort, if there is no documented facility available. */ 93bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic const char *__getProgramName () { 94bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl extern const char *__progname; 95486e5c26dc3164493b4f045b533fc1b9e1847581Felix Kuehling char * arg = strrchr(__progname, '/'); 96486e5c26dc3164493b4f045b533fc1b9e1847581Felix Kuehling if (arg) 97486e5c26dc3164493b4f045b533fc1b9e1847581Felix Kuehling return arg+1; 98486e5c26dc3164493b4f045b533fc1b9e1847581Felix Kuehling else 99486e5c26dc3164493b4f045b533fc1b9e1847581Felix Kuehling return __progname; 100bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 101bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl# define GET_PROGRAM_NAME() __getProgramName() 102bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl# else 103bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl# define GET_PROGRAM_NAME() "" 104fff87eecbe94ca3ac4ca0e7e8647ee7cae7fae56Felix Kuehling# warning "Per application configuration won't work with your OS version." 105bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl# endif 106bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#endif 107bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 108bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Find an option in an option cache with the name as key */ 109bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic GLuint findOption (const driOptionCache *cache, const char *name) { 110bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint len = strlen (name); 111bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint size = 1 << cache->tableSize, mask = size - 1; 112bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint hash = 0; 113bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint i, shift; 114bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 115bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl /* compute a hash from the variable length name */ 116bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (i = 0, shift = 0; i < len; ++i, shift = (shift+8) & 31) 117bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl hash += (GLuint)name[i] << shift; 118bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl hash *= hash; 119bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl hash = (hash >> (16-cache->tableSize/2)) & mask; 120bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 121bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl /* this is just the starting point of the linear search for the option */ 122bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (i = 0; i < size; ++i, hash = (hash+1) & mask) { 123bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl /* if we hit an empty entry then the option is not defined (yet) */ 124bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (cache->info[hash].name == 0) 125bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 126bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else if (!strcmp (name, cache->info[hash].name)) 127bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 128bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 129bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl /* this assertion fails if the hash table is full */ 130bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl assert (i < size); 131bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 132bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return hash; 133bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 134bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 135bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Count the real number of options in an option cache */ 136bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic GLuint countOptions (const driOptionCache *cache) { 137bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint size = 1 << cache->tableSize; 138bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint i, count = 0; 139bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (i = 0; i < size; ++i) 140bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (cache->info[i].name) 141bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl count++; 142bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return count; 143bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 144bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 145bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Like strdup but using MALLOC and with error checking. */ 146bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#define XSTRDUP(dest,source) do { \ 147bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint len = strlen (source); \ 148bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!(dest = MALLOC (len+1))) { \ 149bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); \ 150bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl abort(); \ 151bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } \ 152bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl memcpy (dest, source, len+1); \ 153bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} while (0) 154bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 155bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic int compare (const void *a, const void *b) { 156bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return strcmp (*(char *const*)a, *(char *const*)b); 157bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 158bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Binary search in a string array. */ 159bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic GLuint bsearchStr (const XML_Char *name, 160bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl const XML_Char *elems[], GLuint count) { 161bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl const XML_Char **found; 162bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl found = bsearch (&name, elems, count, sizeof (XML_Char *), compare); 163bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (found) 164bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return found - elems; 165bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else 166bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return count; 167bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 168bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 16994de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling/** \brief Locale-independent integer parser. 17094de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * 17194de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * Works similar to strtol. Leading space is NOT skipped. The input 17294de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * number may have an optional sign. Radix is specified by base. If 17394de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * base is 0 then decimal is assumed unless the input number is 17494de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * prefixed by 0x or 0X for hexadecimal or 0 for octal. After 17594de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * returning tail points to the first character that is not part of 17694de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * the integer number. If no number was found then tail points to the 17794de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * start of the input string. */ 17894de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehlingstatic GLint strToI (const XML_Char *string, const XML_Char **tail, int base) { 17994de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling GLint radix = base == 0 ? 10 : base; 18094de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling GLint result = 0; 18194de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling GLint sign = 1; 18294de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling GLboolean numberFound = GL_FALSE; 18394de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling const XML_Char *start = string; 18494de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling 18594de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling assert (radix >= 2 && radix <= 36); 18694de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling 18794de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling if (*string == '-') { 18894de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling sign = -1; 18994de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling string++; 19094de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } else if (*string == '+') 19194de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling string++; 19294de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling if (base == 0 && *string == '0') { 19394de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling numberFound = GL_TRUE; 19494de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling if (*(string+1) == 'x' || *(string+1) == 'X') { 19594de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling radix = 16; 19694de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling string += 2; 19794de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } else { 19894de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling radix = 8; 19994de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling string++; 20094de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } 20194de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } 20294de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling do { 20394de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling GLint digit = -1; 20494de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling if (radix <= 10) { 20594de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling if (*string >= '0' && *string < '0' + radix) 20694de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling digit = *string - '0'; 20794de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } else { 20894de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling if (*string >= '0' && *string <= '9') 20994de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling digit = *string - '0'; 21094de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling else if (*string >= 'a' && *string < 'a' + radix - 10) 21194de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling digit = *string - 'a' + 10; 21294de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling else if (*string >= 'A' && *string < 'A' + radix - 10) 21394de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling digit = *string - 'A' + 10; 21494de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } 21594de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling if (digit != -1) { 21694de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling numberFound = GL_TRUE; 21794de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling result = radix*result + digit; 21894de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling string++; 21994de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } else 22094de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling break; 22194de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } while (GL_TRUE); 22294de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling *tail = numberFound ? string : start; 22394de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling return sign * result; 22494de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling} 22594de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling 22694de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling/** \brief Locale-independent floating-point parser. 22794de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * 22894de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * Works similar to strtod. Leading space is NOT skipped. The input 22994de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * number may have an optional sign. '.' is interpreted as decimal 23099907303f6a1e9abe02977664ad8457c122213ceTimo Wiren * point and may occur at most once. Optionally the number may end in 23194de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * [eE]<exponent>, where <exponent> is an integer as recognized by 23294de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * strToI. In that case the result is number * 10^exponent. After 23394de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * returning tail points to the first character that is not part of 23494de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * the floating point number. If no number was found then tail points 23594de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * to the start of the input string. 23694de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * 23794de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * Uses two passes for maximum accuracy. */ 23894de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehlingstatic GLfloat strToF (const XML_Char *string, const XML_Char **tail) { 23994de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling GLint nDigits = 0, pointPos, exponent; 24094de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling GLfloat sign = 1.0f, result = 0.0f, scale; 24194de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling const XML_Char *start = string, *numStart; 24294de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling 24394de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling /* sign */ 24494de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling if (*string == '-') { 24594de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling sign = -1.0f; 24694de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling string++; 24794de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } else if (*string == '+') 24894de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling string++; 24994de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling 25094de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling /* first pass: determine position of decimal point, number of 25194de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling * digits, exponent and the end of the number. */ 25294de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling numStart = string; 25394de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling while (*string >= '0' && *string <= '9') { 25494de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling string++; 25594de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling nDigits++; 25694de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } 25794de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling pointPos = nDigits; 25894de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling if (*string == '.') { 25994de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling string++; 26094de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling while (*string >= '0' && *string <= '9') { 26194de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling string++; 26294de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling nDigits++; 26394de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } 26494de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } 26594de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling if (nDigits == 0) { 26694de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling /* no digits, no number */ 26794de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling *tail = start; 26894de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling return 0.0f; 26994de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } 27094de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling *tail = string; 27194de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling if (*string == 'e' || *string == 'E') { 27294de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling const XML_Char *expTail; 27394de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling exponent = strToI (string+1, &expTail, 10); 27494de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling if (expTail == string+1) 27594de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling exponent = 0; 27694de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling else 27794de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling *tail = expTail; 27894de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } else 27994de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling exponent = 0; 28094de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling string = numStart; 28194de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling 28294de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling /* scale of the first digit */ 28322ae633d1ea636e0e07ba044a0f8fa2195c83bc6Alan Hourihane scale = sign * (GLfloat)pow (10.0, (GLdouble)(pointPos-1 + exponent)); 28494de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling 28594de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling /* second pass: parse digits */ 28694de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling do { 28794de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling if (*string != '.') { 28894de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling assert (*string >= '0' && *string <= '9'); 28994de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling result += scale * (GLfloat)(*string - '0'); 29094de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling scale *= 0.1f; 29194de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling nDigits--; 29294de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } 29394de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling string++; 29494de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling } while (nDigits > 0); 29594de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling 29694de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling return result; 29794de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling} 29894de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling 299bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Parse a value of a given type. */ 300bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic GLboolean parseValue (driOptionValue *v, driOptionType type, 301bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl const XML_Char *string) { 302118de7a01369977d13f40bab2ad591320cc7f7ffAlan Hourihane const XML_Char *tail = NULL; 303bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl /* skip leading white-space */ 304bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl string += strspn (string, " \f\n\r\t\v"); 305bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl switch (type) { 306bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case DRI_BOOL: 307bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!strcmp (string, "false")) { 308bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl v->_bool = GL_FALSE; 309bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl tail = string + 5; 310bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } else if (!strcmp (string, "true")) { 311bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl v->_bool = GL_TRUE; 312bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl tail = string + 4; 313bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 314bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else 315bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return GL_FALSE; 316bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 317bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case DRI_ENUM: /* enum is just a special integer */ 318bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case DRI_INT: 31994de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling v->_int = strToI (string, &tail, 0); 320bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 321bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case DRI_FLOAT: 32294de418fd053a2a970d1a1312765f14be7aeb6f6Felix Kuehling v->_float = strToF (string, &tail); 323bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 324bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 325bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 326bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (tail == string) 327bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return GL_FALSE; /* empty string (or containing only white-space) */ 328bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl /* skip trailing white space */ 329bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (*tail) 330bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl tail += strspn (tail, " \f\n\r\t\v"); 331bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (*tail) 332bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return GL_FALSE; /* something left over that is not part of value */ 333bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 334bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return GL_TRUE; 335bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 336bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 337bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Parse a list of ranges of type info->type. */ 338bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic GLboolean parseRanges (driOptionInfo *info, const XML_Char *string) { 339bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_Char *cp, *range; 340bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint nRanges, i; 341bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl driOptionRange *ranges; 342bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 343bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XSTRDUP (cp, string); 344bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl /* pass 1: determine the number of ranges (number of commas + 1) */ 345bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl range = cp; 346bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (nRanges = 1; *range; ++range) 347bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (*range == ',') 348bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl ++nRanges; 349bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 350bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if ((ranges = MALLOC (nRanges*sizeof(driOptionRange))) == NULL) { 351bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); 352bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl abort(); 353bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 354bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 355bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl /* pass 2: parse all ranges into preallocated array */ 356bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl range = cp; 357bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (i = 0; i < nRanges; ++i) { 358bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_Char *end, *sep; 359bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl assert (range); 360bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl end = strchr (range, ','); 361bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (end) 362bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl *end = '\0'; 363bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl sep = strchr (range, ':'); 364bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (sep) { /* non-empty interval */ 365bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl *sep = '\0'; 366bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!parseValue (&ranges[i].start, info->type, range) || 367bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl !parseValue (&ranges[i].end, info->type, sep+1)) 368bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 369bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (info->type == DRI_INT && 370bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl ranges[i].start._int > ranges[i].end._int) 371bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 372bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (info->type == DRI_FLOAT && 373bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl ranges[i].start._float > ranges[i].end._float) 374bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 375bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } else { /* empty interval */ 376bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!parseValue (&ranges[i].start, info->type, range)) 377bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 378bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl ranges[i].end = ranges[i].start; 379bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 380bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (end) 381bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl range = end+1; 382bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else 383bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl range = NULL; 384bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 385bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl FREE (cp); 386bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (i < nRanges) { 387bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl FREE (ranges); 388bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return GL_FALSE; 389bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } else 390bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl assert (range == NULL); 391bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 392bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl info->nRanges = nRanges; 393bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl info->ranges = ranges; 394bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return GL_TRUE; 395bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 396bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 397bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Check if a value is in one of info->ranges. */ 398bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic GLboolean checkValue (const driOptionValue *v, const driOptionInfo *info) { 399bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint i; 400bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl assert (info->type != DRI_BOOL); /* should be caught by the parser */ 401bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (info->nRanges == 0) 402bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return GL_TRUE; 403bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl switch (info->type) { 404bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case DRI_ENUM: /* enum is just a special integer */ 405bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case DRI_INT: 406bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (i = 0; i < info->nRanges; ++i) 407bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (v->_int >= info->ranges[i].start._int && 408bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl v->_int <= info->ranges[i].end._int) 409bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return GL_TRUE; 410bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 411bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case DRI_FLOAT: 412bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (i = 0; i < info->nRanges; ++i) 413bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (v->_float >= info->ranges[i].start._float && 414bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl v->_float <= info->ranges[i].end._float) 415bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return GL_TRUE; 416bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 417bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl default: 418bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl assert (0); /* should never happen */ 419bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 420bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return GL_FALSE; 421bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 422bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 423ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis/** 424ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis * Print message to \c stderr if the \c LIBGL_DEBUG environment variable 425ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis * is set. 426ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis * 427ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis * Is called from the drivers. 428ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis * 429ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis * \param f \c printf like format string. 430ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis */ 431ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzisstatic void 432ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis__driUtilMessage(const char *f, ...) 433ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis{ 434ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis va_list args; 435ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis 436ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis if (getenv("LIBGL_DEBUG")) { 437ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis fprintf(stderr, "libGL: "); 438ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis va_start(args, f); 439ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis vfprintf(stderr, f, args); 440ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis va_end(args); 441ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis fprintf(stderr, "\n"); 442ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis } 443ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis} 444ceda4da8573cca85e02d0e7c2db41f9151683321George Sapountzis 445bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Output a warning message. */ 446bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#define XML_WARNING1(msg) do {\ 447bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \ 4482f3e939ae719f522fc26bfd62997fa8b7940c8edKristian Høgsberg (int) XML_GetCurrentLineNumber(data->parser), \ 4492f3e939ae719f522fc26bfd62997fa8b7940c8edKristian Høgsberg (int) XML_GetCurrentColumnNumber(data->parser)); \ 450bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} while (0) 451bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#define XML_WARNING(msg,args...) do { \ 452bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \ 4532f3e939ae719f522fc26bfd62997fa8b7940c8edKristian Høgsberg (int) XML_GetCurrentLineNumber(data->parser), \ 4542f3e939ae719f522fc26bfd62997fa8b7940c8edKristian Høgsberg (int) XML_GetCurrentColumnNumber(data->parser), \ 455bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl args); \ 456bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} while (0) 457bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Output an error message. */ 458bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#define XML_ERROR1(msg) do { \ 459bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \ 4602f3e939ae719f522fc26bfd62997fa8b7940c8edKristian Høgsberg (int) XML_GetCurrentLineNumber(data->parser), \ 4612f3e939ae719f522fc26bfd62997fa8b7940c8edKristian Høgsberg (int) XML_GetCurrentColumnNumber(data->parser)); \ 462bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} while (0) 463bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#define XML_ERROR(msg,args...) do { \ 464bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \ 4652f3e939ae719f522fc26bfd62997fa8b7940c8edKristian Høgsberg (int) XML_GetCurrentLineNumber(data->parser), \ 4662f3e939ae719f522fc26bfd62997fa8b7940c8edKristian Høgsberg (int) XML_GetCurrentColumnNumber(data->parser), \ 467bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl args); \ 468bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} while (0) 469bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Output a fatal error message and abort. */ 470bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#define XML_FATAL1(msg) do { \ 471bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \ 472bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->name, \ 4732f3e939ae719f522fc26bfd62997fa8b7940c8edKristian Høgsberg (int) XML_GetCurrentLineNumber(data->parser), \ 4742f3e939ae719f522fc26bfd62997fa8b7940c8edKristian Høgsberg (int) XML_GetCurrentColumnNumber(data->parser)); \ 475bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl abort();\ 476bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} while (0) 477bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#define XML_FATAL(msg,args...) do { \ 478bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \ 479bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->name, \ 4802f3e939ae719f522fc26bfd62997fa8b7940c8edKristian Høgsberg (int) XML_GetCurrentLineNumber(data->parser), \ 4812f3e939ae719f522fc26bfd62997fa8b7940c8edKristian Høgsberg (int) XML_GetCurrentColumnNumber(data->parser), \ 482bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl args); \ 483bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl abort();\ 484bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} while (0) 485bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 486bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Parser context for __driConfigOptions. */ 487bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstruct OptInfoData { 488bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl const char *name; 489bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_Parser parser; 490bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl driOptionCache *cache; 491bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLboolean inDriInfo; 492bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLboolean inSection; 493bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLboolean inDesc; 494bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLboolean inOption; 495bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLboolean inEnum; 496bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl int curOption; 497bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl}; 498bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 499bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Elements in __driConfigOptions. */ 500bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlenum OptInfoElem { 501bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl OI_DESCRIPTION = 0, OI_DRIINFO, OI_ENUM, OI_OPTION, OI_SECTION, OI_COUNT 502bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl}; 503bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic const XML_Char *OptInfoElems[] = { 504bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl "description", "driinfo", "enum", "option", "section" 505bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl}; 506bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 507bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Parse attributes of an enum element. 508bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * 509bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * We're not actually interested in the data. Just make sure this is ok 510bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * for external configuration tools. 511bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl */ 512bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic void parseEnumAttr (struct OptInfoData *data, const XML_Char **attr) { 513bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint i; 514bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl const XML_Char *value = NULL, *text = NULL; 515bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl driOptionValue v; 516bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint opt = data->curOption; 517bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (i = 0; attr[i]; i += 2) { 518bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!strcmp (attr[i], "value")) value = attr[i+1]; 519bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else if (!strcmp (attr[i], "text")) text = attr[i+1]; 520bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else XML_FATAL("illegal enum attribute: %s.", attr[i]); 521bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 522bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!value) XML_FATAL1 ("value attribute missing in enum."); 523bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!text) XML_FATAL1 ("text attribute missing in enum."); 524bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!parseValue (&v, data->cache->info[opt].type, value)) 525bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL ("illegal enum value: %s.", value); 526bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!checkValue (&v, &data->cache->info[opt])) 527bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL ("enum value out of valid range: %s.", value); 528bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 529bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 530bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Parse attributes of a description element. 531bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * 532bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * We're not actually interested in the data. Just make sure this is ok 533bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * for external configuration tools. 534bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl */ 535bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic void parseDescAttr (struct OptInfoData *data, const XML_Char **attr) { 536bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint i; 537bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl const XML_Char *lang = NULL, *text = NULL; 538bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (i = 0; attr[i]; i += 2) { 539bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!strcmp (attr[i], "lang")) lang = attr[i+1]; 540bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else if (!strcmp (attr[i], "text")) text = attr[i+1]; 541bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else XML_FATAL("illegal description attribute: %s.", attr[i]); 542bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 543bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!lang) XML_FATAL1 ("lang attribute missing in description."); 544bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!text) XML_FATAL1 ("text attribute missing in description."); 545bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 546bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 547bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Parse attributes of an option element. */ 548bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic void parseOptInfoAttr (struct OptInfoData *data, const XML_Char **attr) { 549bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl enum OptAttr {OA_DEFAULT = 0, OA_NAME, OA_TYPE, OA_VALID, OA_COUNT}; 550bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl static const XML_Char *optAttr[] = {"default", "name", "type", "valid"}; 551bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl const XML_Char *attrVal[OA_COUNT] = {NULL, NULL, NULL, NULL}; 552bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl const char *defaultVal; 553bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl driOptionCache *cache = data->cache; 554bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint opt, i; 555bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (i = 0; attr[i]; i += 2) { 556bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint attrName = bsearchStr (attr[i], optAttr, OA_COUNT); 557bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (attrName >= OA_COUNT) 558bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL ("illegal option attribute: %s", attr[i]); 559bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl attrVal[attrName] = attr[i+1]; 560bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 561bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!attrVal[OA_NAME]) XML_FATAL1 ("name attribute missing in option."); 562bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!attrVal[OA_TYPE]) XML_FATAL1 ("type attribute missing in option."); 563bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!attrVal[OA_DEFAULT]) XML_FATAL1 ("default attribute missing in option."); 564bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 565bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl opt = findOption (cache, attrVal[OA_NAME]); 566bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (cache->info[opt].name) 567bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL ("option %s redefined.", attrVal[OA_NAME]); 568bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->curOption = opt; 569bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 570bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XSTRDUP (cache->info[opt].name, attrVal[OA_NAME]); 571bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 572bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!strcmp (attrVal[OA_TYPE], "bool")) 573bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl cache->info[opt].type = DRI_BOOL; 574bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else if (!strcmp (attrVal[OA_TYPE], "enum")) 575bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl cache->info[opt].type = DRI_ENUM; 576bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else if (!strcmp (attrVal[OA_TYPE], "int")) 577bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl cache->info[opt].type = DRI_INT; 578bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else if (!strcmp (attrVal[OA_TYPE], "float")) 579bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl cache->info[opt].type = DRI_FLOAT; 580bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else 581bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL ("illegal type in option: %s.", attrVal[OA_TYPE]); 582bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 583bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl defaultVal = getenv (cache->info[opt].name); 584bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (defaultVal != NULL) { 585bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl /* don't use XML_WARNING, we want the user to see this! */ 586bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl fprintf (stderr, 587bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl "ATTENTION: default value of option %s overridden by environment.\n", 588bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl cache->info[opt].name); 589bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } else 590bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl defaultVal = attrVal[OA_DEFAULT]; 591bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!parseValue (&cache->values[opt], cache->info[opt].type, defaultVal)) 592b629d5ba24f76ed6af35455a874d351fde1e5bbeLauri Kasanen XML_FATAL ("illegal default value for %s: %s.", cache->info[opt].name, defaultVal); 593bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 594bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (attrVal[OA_VALID]) { 595bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (cache->info[opt].type == DRI_BOOL) 596bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL1 ("boolean option with valid attribute."); 597bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!parseRanges (&cache->info[opt], attrVal[OA_VALID])) 598bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL ("illegal valid attribute: %s.", attrVal[OA_VALID]); 599bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!checkValue (&cache->values[opt], &cache->info[opt])) 600bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL ("default value out of valid range '%s': %s.", 601bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl attrVal[OA_VALID], defaultVal); 602bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } else if (cache->info[opt].type == DRI_ENUM) { 603bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL1 ("valid attribute missing in option (mandatory for enums)."); 604bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } else { 605bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl cache->info[opt].nRanges = 0; 606bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl cache->info[opt].ranges = NULL; 607bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 608bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 609bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 610bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Handler for start element events. */ 611bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic void optInfoStartElem (void *userData, const XML_Char *name, 612bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl const XML_Char **attr) { 613bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl struct OptInfoData *data = (struct OptInfoData *)userData; 614bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT); 615bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl switch (elem) { 616bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OI_DRIINFO: 617bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (data->inDriInfo) 618bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL1 ("nested <driinfo> elements."); 619bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (attr[0]) 620bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL1 ("attributes specified on <driinfo> element."); 621bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inDriInfo = GL_TRUE; 622bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 623bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OI_SECTION: 624bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!data->inDriInfo) 625bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL1 ("<section> must be inside <driinfo>."); 626bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (data->inSection) 627bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL1 ("nested <section> elements."); 628bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (attr[0]) 629bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL1 ("attributes specified on <section> element."); 630bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inSection = GL_TRUE; 631bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 632bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OI_DESCRIPTION: 633bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!data->inSection && !data->inOption) 634bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL1 ("<description> must be inside <description> or <option."); 635bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (data->inDesc) 636bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL1 ("nested <description> elements."); 637bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inDesc = GL_TRUE; 638bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl parseDescAttr (data, attr); 639bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 640bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OI_OPTION: 641bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!data->inSection) 642bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL1 ("<option> must be inside <section>."); 643bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (data->inDesc) 644bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL1 ("<option> nested in <description> element."); 645bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (data->inOption) 646bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL1 ("nested <option> elements."); 647bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inOption = GL_TRUE; 648bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl parseOptInfoAttr (data, attr); 649bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 650bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OI_ENUM: 651bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!(data->inOption && data->inDesc)) 652bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL1 ("<enum> must be inside <option> and <description>."); 653bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (data->inEnum) 654bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL1 ("nested <enum> elements."); 655bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inEnum = GL_TRUE; 656bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl parseEnumAttr (data, attr); 657bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 658bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl default: 659bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL ("unknown element: %s.", name); 660bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 661bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 662bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 663bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Handler for end element events. */ 664bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic void optInfoEndElem (void *userData, const XML_Char *name) { 665bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl struct OptInfoData *data = (struct OptInfoData *)userData; 666bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT); 667bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl switch (elem) { 668bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OI_DRIINFO: 669bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inDriInfo = GL_FALSE; 670bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 671bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OI_SECTION: 672bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inSection = GL_FALSE; 673bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 674bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OI_DESCRIPTION: 675bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inDesc = GL_FALSE; 676bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 677bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OI_OPTION: 678bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inOption = GL_FALSE; 679bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 680bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OI_ENUM: 681bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inEnum = GL_FALSE; 682bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 683bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl default: 684bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl assert (0); /* should have been caught by StartElem */ 685bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 686bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 687bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 688d450d0b0e228e5b16c04b2a1acb9ea549aa690f2Brian Paulvoid driParseOptionInfo (driOptionCache *info, 689d450d0b0e228e5b16c04b2a1acb9ea549aa690f2Brian Paul const char *configOptions, GLuint nConfigOptions) { 690bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_Parser p; 691bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl int status; 692bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl struct OptInfoData userData; 693bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl struct OptInfoData *data = &userData; 694d450d0b0e228e5b16c04b2a1acb9ea549aa690f2Brian Paul GLuint realNoptions; 695bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 696fff87eecbe94ca3ac4ca0e7e8647ee7cae7fae56Felix Kuehling /* determine hash table size and allocate memory: 697fff87eecbe94ca3ac4ca0e7e8647ee7cae7fae56Felix Kuehling * 3/2 of the number of options, rounded up, so there remains always 698fff87eecbe94ca3ac4ca0e7e8647ee7cae7fae56Felix Kuehling * at least one free entry. This is needed for detecting undefined 699fff87eecbe94ca3ac4ca0e7e8647ee7cae7fae56Felix Kuehling * options in configuration files without getting a hash table overflow. 700fff87eecbe94ca3ac4ca0e7e8647ee7cae7fae56Felix Kuehling * Round this up to a power of two. */ 701fff87eecbe94ca3ac4ca0e7e8647ee7cae7fae56Felix Kuehling GLuint minSize = (nConfigOptions*3 + 1) / 2; 702bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint size, log2size; 703fff87eecbe94ca3ac4ca0e7e8647ee7cae7fae56Felix Kuehling for (size = 1, log2size = 0; size < minSize; size <<= 1, ++log2size); 704bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl info->tableSize = log2size; 705bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl info->info = CALLOC (size * sizeof (driOptionInfo)); 706fff87eecbe94ca3ac4ca0e7e8647ee7cae7fae56Felix Kuehling info->values = CALLOC (size * sizeof (driOptionValue)); 707bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (info->info == NULL || info->values == NULL) { 708bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); 709bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl abort(); 710bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 711bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 712bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl p = XML_ParserCreate ("UTF-8"); /* always UTF-8 */ 713bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_SetElementHandler (p, optInfoStartElem, optInfoEndElem); 714bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_SetUserData (p, data); 715bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 716bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.name = "__driConfigOptions"; 717bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.parser = p; 718bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.cache = info; 719bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.inDriInfo = GL_FALSE; 720bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.inSection = GL_FALSE; 721bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.inDesc = GL_FALSE; 722bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.inOption = GL_FALSE; 723bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.inEnum = GL_FALSE; 724bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.curOption = -1; 725bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 726d450d0b0e228e5b16c04b2a1acb9ea549aa690f2Brian Paul status = XML_Parse (p, configOptions, strlen (configOptions), 1); 727bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!status) 728bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_FATAL ("%s.", XML_ErrorString(XML_GetErrorCode(p))); 729bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 730bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_ParserFree (p); 731bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 732d450d0b0e228e5b16c04b2a1acb9ea549aa690f2Brian Paul /* Check if the actual number of options matches nConfigOptions. 733bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * A mismatch is not fatal (a hash table overflow would be) but we 734bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl * want the driver developer's attention anyway. */ 735d450d0b0e228e5b16c04b2a1acb9ea549aa690f2Brian Paul realNoptions = countOptions (info); 736d450d0b0e228e5b16c04b2a1acb9ea549aa690f2Brian Paul if (realNoptions != nConfigOptions) { 737bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl fprintf (stderr, 738d450d0b0e228e5b16c04b2a1acb9ea549aa690f2Brian Paul "Error: nConfigOptions (%u) does not match the actual number of options in\n" 739bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl " __driConfigOptions (%u).\n", 740d450d0b0e228e5b16c04b2a1acb9ea549aa690f2Brian Paul nConfigOptions, realNoptions); 741bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 742bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 743bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 744bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Parser context for configuration files. */ 745bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstruct OptConfData { 746bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl const char *name; 747bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_Parser parser; 748bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl driOptionCache *cache; 749bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLint screenNum; 750bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl const char *driverName, *execName; 751bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint ignoringDevice; 752bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint ignoringApp; 753bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint inDriConf; 754bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint inDevice; 755bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint inApp; 756bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint inOption; 757bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl}; 758bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 759bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Elements in configuration files. */ 760bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlenum OptConfElem { 761bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl OC_APPLICATION = 0, OC_DEVICE, OC_DRICONF, OC_OPTION, OC_COUNT 762bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl}; 763bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic const XML_Char *OptConfElems[] = { 764bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl "application", "device", "driconf", "option" 765bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl}; 766bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 767bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Parse attributes of a device element. */ 768bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic void parseDeviceAttr (struct OptConfData *data, const XML_Char **attr) { 769bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint i; 770bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl const XML_Char *driver = NULL, *screen = NULL; 771bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (i = 0; attr[i]; i += 2) { 772bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!strcmp (attr[i], "driver")) driver = attr[i+1]; 773bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else if (!strcmp (attr[i], "screen")) screen = attr[i+1]; 77499907303f6a1e9abe02977664ad8457c122213ceTimo Wiren else XML_WARNING("unknown device attribute: %s.", attr[i]); 775bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 776bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (driver && strcmp (driver, data->driverName)) 777bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->ignoringDevice = data->inDevice; 778bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else if (screen) { 779bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl driOptionValue screenNum; 780bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!parseValue (&screenNum, DRI_INT, screen)) 781bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_WARNING("illegal screen number: %s.", screen); 782bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else if (screenNum._int != data->screenNum) 783bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->ignoringDevice = data->inDevice; 784bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 785bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 786bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 787bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Parse attributes of an application element. */ 788bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic void parseAppAttr (struct OptConfData *data, const XML_Char **attr) { 789bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint i; 7907854b8cb166e513300085f8798b3fd05ae6a492eMarek Olšák const XML_Char *exec = NULL; 791bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (i = 0; attr[i]; i += 2) { 7927854b8cb166e513300085f8798b3fd05ae6a492eMarek Olšák if (!strcmp (attr[i], "name")) /* not needed here */; 793bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else if (!strcmp (attr[i], "executable")) exec = attr[i+1]; 79499907303f6a1e9abe02977664ad8457c122213ceTimo Wiren else XML_WARNING("unknown application attribute: %s.", attr[i]); 795bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 796bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (exec && strcmp (exec, data->execName)) 797bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->ignoringApp = data->inApp; 798bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 799bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 800bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Parse attributes of an option element. */ 801bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic void parseOptConfAttr (struct OptConfData *data, const XML_Char **attr) { 802bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint i; 803bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl const XML_Char *name = NULL, *value = NULL; 804bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (i = 0; attr[i]; i += 2) { 805bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!strcmp (attr[i], "name")) name = attr[i+1]; 806bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else if (!strcmp (attr[i], "value")) value = attr[i+1]; 80799907303f6a1e9abe02977664ad8457c122213ceTimo Wiren else XML_WARNING("unknown option attribute: %s.", attr[i]); 808bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 809bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!name) XML_WARNING1 ("name attribute missing in option."); 810bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!value) XML_WARNING1 ("value attribute missing in option."); 811bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (name && value) { 812bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl driOptionCache *cache = data->cache; 813bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint opt = findOption (cache, name); 814bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (cache->info[opt].name == NULL) 815bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_WARNING ("undefined option: %s.", name); 816bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else if (getenv (cache->info[opt].name)) 817bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl /* don't use XML_WARNING, we want the user to see this! */ 818bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl fprintf (stderr, "ATTENTION: option value of option %s ignored.\n", 819bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl cache->info[opt].name); 820bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else if (!parseValue (&cache->values[opt], cache->info[opt].type, value)) 821bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_WARNING ("illegal option value: %s.", value); 822bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 823bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 824bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 825bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Handler for start element events. */ 826bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic void optConfStartElem (void *userData, const XML_Char *name, 827bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl const XML_Char **attr) { 828bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl struct OptConfData *data = (struct OptConfData *)userData; 829bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT); 830bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl switch (elem) { 831bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OC_DRICONF: 832bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (data->inDriConf) 833bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_WARNING1 ("nested <driconf> elements."); 834bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (attr[0]) 835bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_WARNING1 ("attributes specified on <driconf> element."); 836bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inDriConf++; 837bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 838bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OC_DEVICE: 839bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!data->inDriConf) 840bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_WARNING1 ("<device> should be inside <driconf>."); 841bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (data->inDevice) 842bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_WARNING1 ("nested <device> elements."); 843bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inDevice++; 844bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!data->ignoringDevice && !data->ignoringApp) 845bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl parseDeviceAttr (data, attr); 846bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 847bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OC_APPLICATION: 848bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!data->inDevice) 849bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_WARNING1 ("<application> should be inside <device>."); 850bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (data->inApp) 851bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_WARNING1 ("nested <application> elements."); 852bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inApp++; 853bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!data->ignoringDevice && !data->ignoringApp) 854bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl parseAppAttr (data, attr); 855bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 856bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OC_OPTION: 857bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!data->inApp) 858bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_WARNING1 ("<option> should be inside <application>."); 859bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (data->inOption) 860bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_WARNING1 ("nested <option> elements."); 861bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inOption++; 862bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!data->ignoringDevice && !data->ignoringApp) 863bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl parseOptConfAttr (data, attr); 864bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 865bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl default: 866bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_WARNING ("unknown element: %s.", name); 867bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 868bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 869bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 870bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Handler for end element events. */ 871bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic void optConfEndElem (void *userData, const XML_Char *name) { 872bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl struct OptConfData *data = (struct OptConfData *)userData; 873bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT); 874bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl switch (elem) { 875bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OC_DRICONF: 876bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inDriConf--; 877bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 878bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OC_DEVICE: 879bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (data->inDevice-- == data->ignoringDevice) 880bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->ignoringDevice = 0; 881bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 882bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OC_APPLICATION: 883bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (data->inApp-- == data->ignoringApp) 884bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->ignoringApp = 0; 885bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 886bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl case OC_OPTION: 887bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->inOption--; 888bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 889bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl default: 890bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl /* unknown element, warning was produced on start tag */; 891bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 892bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 893bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 894bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Initialize an option cache based on info */ 89597fcc0e77b55f2d11a4fe34fbe71605d0550e6c8Brian Paulstatic void initOptionCache (driOptionCache *cache, const driOptionCache *info) { 896bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl cache->info = info->info; 897bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl cache->tableSize = info->tableSize; 898bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl cache->values = MALLOC ((1<<info->tableSize) * sizeof (driOptionValue)); 899bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (cache->values == NULL) { 900bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); 901bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl abort(); 902bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 903bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl memcpy (cache->values, info->values, 904bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl (1<<info->tableSize) * sizeof (driOptionValue)); 905bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 906bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 907bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl/** \brief Parse the named configuration file */ 908bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlstatic void parseOneConfigFile (XML_Parser p) { 909bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#define BUF_SIZE 0x1000 910bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl struct OptConfData *data = (struct OptConfData *)XML_GetUserData (p); 911bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl int status; 912bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl int fd; 913bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 914bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if ((fd = open (data->name, O_RDONLY)) == -1) { 915bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl __driUtilMessage ("Can't open configuration file %s: %s.", 916bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->name, strerror (errno)); 917bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return; 918bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 919bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 920bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl while (1) { 921bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl int bytesRead; 922bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl void *buffer = XML_GetBuffer (p, BUF_SIZE); 923bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!buffer) { 924bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl __driUtilMessage ("Can't allocate parser buffer."); 925bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 926bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 927bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl bytesRead = read (fd, buffer, BUF_SIZE); 928bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (bytesRead == -1) { 929bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl __driUtilMessage ("Error reading from configuration file %s: %s.", 930bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl data->name, strerror (errno)); 931bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 932bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 933bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl status = XML_ParseBuffer (p, bytesRead, bytesRead == 0); 934bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (!status) { 935bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_ERROR ("%s.", XML_ErrorString(XML_GetErrorCode(p))); 936bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 937bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 938bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (bytesRead == 0) 939bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl break; 940bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 941bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 942bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl close (fd); 943bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl#undef BUF_SIZE 944bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 945bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 94697fcc0e77b55f2d11a4fe34fbe71605d0550e6c8Brian Paulvoid driParseConfigFiles (driOptionCache *cache, const driOptionCache *info, 947bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLint screenNum, const char *driverName) { 948bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl char *filenames[2] = {"/etc/drirc", NULL}; 949bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl char *home; 950bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint i; 951bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl struct OptConfData userData; 952bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 953bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl initOptionCache (cache, info); 954bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 955bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.cache = cache; 956bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.screenNum = screenNum; 957bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.driverName = driverName; 958bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.execName = GET_PROGRAM_NAME(); 959bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 960bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if ((home = getenv ("HOME"))) { 961bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint len = strlen (home); 962bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl filenames[1] = MALLOC (len + 7+1); 963bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (filenames[1] == NULL) 964bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl __driUtilMessage ("Can't allocate memory for %s/.drirc.", home); 965bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl else { 966bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl memcpy (filenames[1], home, len); 967bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl memcpy (filenames[1] + len, "/.drirc", 7+1); 968bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 969bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 970bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 971bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (i = 0; i < 2; ++i) { 972bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_Parser p; 973bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (filenames[i] == NULL) 974bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl continue; 975bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 976bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl p = XML_ParserCreate (NULL); /* use encoding specified by file */ 977bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_SetElementHandler (p, optConfStartElem, optConfEndElem); 978bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_SetUserData (p, &userData); 979bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.parser = p; 980bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.name = filenames[i]; 981bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.ignoringDevice = 0; 982bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.ignoringApp = 0; 983bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.inDriConf = 0; 984bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.inDevice = 0; 985bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.inApp = 0; 986bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl userData.inOption = 0; 987bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 988bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl parseOneConfigFile (p); 989bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl XML_ParserFree (p); 990bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 991bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 992bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (filenames[1]) 993bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl FREE (filenames[1]); 994bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 995bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 996bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlvoid driDestroyOptionInfo (driOptionCache *info) { 997bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl driDestroyOptionCache (info); 998bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (info->info) { 999bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint i, size = 1 << info->tableSize; 1000bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl for (i = 0; i < size; ++i) { 1001bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (info->info[i].name) { 1002bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl FREE (info->info[i].name); 1003bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (info->info[i].ranges) 1004bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl FREE (info->info[i].ranges); 1005bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 1006bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 1007bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl FREE (info->info); 1008bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl } 1009bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 1010bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 1011bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirlvoid driDestroyOptionCache (driOptionCache *cache) { 1012bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl if (cache->values) 1013bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl FREE (cache->values); 1014bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 1015bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 1016bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon SmirlGLboolean driCheckOption (const driOptionCache *cache, const char *name, 1017bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl driOptionType type) { 1018bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint i = findOption (cache, name); 1019bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return cache->info[i].name != NULL && cache->info[i].type == type; 1020bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 1021bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 1022bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon SmirlGLboolean driQueryOptionb (const driOptionCache *cache, const char *name) { 1023bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint i = findOption (cache, name); 1024bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl /* make sure the option is defined and has the correct type */ 1025bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl assert (cache->info[i].name != NULL); 1026bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl assert (cache->info[i].type == DRI_BOOL); 1027bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return cache->values[i]._bool; 1028bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 1029bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 1030bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon SmirlGLint driQueryOptioni (const driOptionCache *cache, const char *name) { 1031bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint i = findOption (cache, name); 1032bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl /* make sure the option is defined and has the correct type */ 1033bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl assert (cache->info[i].name != NULL); 1034bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl assert (cache->info[i].type == DRI_INT || cache->info[i].type == DRI_ENUM); 1035bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return cache->values[i]._int; 1036bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 1037bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl 1038bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon SmirlGLfloat driQueryOptionf (const driOptionCache *cache, const char *name) { 1039bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl GLuint i = findOption (cache, name); 1040bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl /* make sure the option is defined and has the correct type */ 1041bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl assert (cache->info[i].name != NULL); 1042bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl assert (cache->info[i].type == DRI_FLOAT); 1043bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl return cache->values[i]._float; 1044bcc6eddd335e97d49ed2ef3a1440f94d58dce12dJon Smirl} 1045