📄 xmlconfig.c
字号:
p = XML_ParserCreate ("UTF-8"); /* always UTF-8 */ XML_SetElementHandler (p, optInfoStartElem, optInfoEndElem); XML_SetUserData (p, data); 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.curOption = -1; status = XML_Parse (p, configOptions, strlen (configOptions), 1); if (!status) 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. */struct OptConfData { const char *name; XML_Parser parser; driOptionCache *cache; GLint screenNum; const char *driverName, *execName; GLuint ignoringDevice; GLuint ignoringApp; GLuint inDriConf; GLuint inDevice; GLuint inApp; GLuint inOption;};/** \brief Elements in configuration files. */enum OptConfElem { OC_APPLICATION = 0, OC_DEVICE, OC_DRICONF, OC_OPTION, OC_COUNT};static const XML_Char *OptConfElems[] = { "application", "device", "driconf", "option"};/** \brief Parse attributes of a device element. */static void parseDeviceAttr (struct OptConfData *data, const XML_Char **attr) { GLuint 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]); } if (driver && strcmp (driver, data->driverName)) data->ignoringDevice = data->inDevice; else if (screen) { driOptionValue screenNum; if (!parseValue (&screenNum, DRI_INT, screen)) XML_WARNING("illegal screen number: %s.", screen); else if (screenNum._int != data->screenNum) data->ignoringDevice = data->inDevice; }}/** \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; for (i = 0; attr[i]; i += 2) { if (!strcmp (attr[i], "name")) name = attr[i+1]; else if (!strcmp (attr[i], "executable")) exec = attr[i+1]; else XML_WARNING("unkown application attribute: %s.", attr[i]); } if (exec && strcmp (exec, data->execName)) data->ignoringApp = data->inApp;}/** \brief Parse attributes of an option element. */static void parseOptConfAttr (struct OptConfData *data, const XML_Char **attr) { GLuint 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]); } 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); if (cache->info[opt].name == NULL) XML_WARNING ("undefined option: %s.", name); 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", cache->info[opt].name); else if (!parseValue (&cache->values[opt], cache->info[opt].type, value)) XML_WARNING ("illegal option value: %s.", value); }}/** \brief Handler for start element events. */static void optConfStartElem (void *userData, const XML_Char *name, const XML_Char **attr) { struct OptConfData *data = (struct OptConfData *)userData; enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT); switch (elem) { case OC_DRICONF: if (data->inDriConf) XML_WARNING1 ("nested <driconf> elements."); if (attr[0]) XML_WARNING1 ("attributes specified on <driconf> element."); data->inDriConf++; break; case OC_DEVICE: if (!data->inDriConf) XML_WARNING1 ("<device> should be inside <driconf>."); if (data->inDevice) XML_WARNING1 ("nested <device> elements."); data->inDevice++; if (!data->ignoringDevice && !data->ignoringApp) parseDeviceAttr (data, attr); break; case OC_APPLICATION: if (!data->inDevice) XML_WARNING1 ("<application> should be inside <device>."); if (data->inApp) XML_WARNING1 ("nested <application> elements."); data->inApp++; if (!data->ignoringDevice && !data->ignoringApp) parseAppAttr (data, attr); break; case OC_OPTION: if (!data->inApp) XML_WARNING1 ("<option> should be inside <application>."); if (data->inOption) XML_WARNING1 ("nested <option> elements."); data->inOption++; if (!data->ignoringDevice && !data->ignoringApp) parseOptConfAttr (data, attr); break; default: XML_WARNING ("unknown element: %s.", name); }}/** \brief Handler for end element events. */static void optConfEndElem (void *userData, const XML_Char *name) { struct OptConfData *data = (struct OptConfData *)userData; enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT); switch (elem) { case OC_DRICONF: data->inDriConf--; break; case OC_DEVICE: if (data->inDevice-- == data->ignoringDevice) data->ignoringDevice = 0; break; case OC_APPLICATION: if (data->inApp-- == data->ignoringApp) data->ignoringApp = 0; break; case OC_OPTION: data->inOption--; break; default: /* unknown element, warning was produced on start tag */; }}/** \brief Initialize an option cache based on info */static void initOptionCache (driOptionCache *cache, const driOptionCache *info) { cache->info = info->info; cache->tableSize = info->tableSize; 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));}/** \brief Parse the named configuration file */static void parseOneConfigFile (XML_Parser p) {#define BUF_SIZE 0x1000 struct OptConfData *data = (struct OptConfData *)XML_GetUserData (p); int status; int fd; if ((fd = open (data->name, O_RDONLY)) == -1) { __driUtilMessage ("Can't open configuration file %s: %s.", data->name, strerror (errno)); return; } while (1) { int bytesRead; void *buffer = XML_GetBuffer (p, BUF_SIZE); if (!buffer) { __driUtilMessage ("Can't allocate parser buffer."); break; } bytesRead = read (fd, buffer, BUF_SIZE); if (bytesRead == -1) { __driUtilMessage ("Error reading from configuration file %s: %s.", data->name, strerror (errno)); break; } status = XML_ParseBuffer (p, bytesRead, bytesRead == 0); if (!status) { XML_ERROR ("%s.", XML_ErrorString(XML_GetErrorCode(p))); break; } if (bytesRead == 0) break; } close (fd);#undef BUF_SIZE}void driParseConfigFiles (driOptionCache *cache, const driOptionCache *info, GLint screenNum, const char *driverName) { char *filenames[2] = {"/etc/drirc", NULL}; char *home; GLuint i; struct OptConfData userData; initOptionCache (cache, info); userData.cache = cache; userData.screenNum = screenNum; userData.driverName = driverName; userData.execName = GET_PROGRAM_NAME(); if ((home = getenv ("HOME"))) { GLuint len = strlen (home); filenames[1] = MALLOC (len + 7+1); if (filenames[1] == NULL) __driUtilMessage ("Can't allocate memory for %s/.drirc.", home); else { memcpy (filenames[1], home, len); memcpy (filenames[1] + len, "/.drirc", 7+1); } } for (i = 0; i < 2; ++i) { XML_Parser p; if (filenames[i] == NULL) continue; p = XML_ParserCreate (NULL); /* use encoding specified by file */ XML_SetElementHandler (p, optConfStartElem, optConfEndElem); XML_SetUserData (p, &userData); userData.parser = p; userData.name = filenames[i]; userData.ignoringDevice = 0; userData.ignoringApp = 0; userData.inDriConf = 0; userData.inDevice = 0; userData.inApp = 0; userData.inOption = 0; parseOneConfigFile (p); XML_ParserFree (p); } if (filenames[1]) FREE (filenames[1]);}void driDestroyOptionInfo (driOptionCache *info) { driDestroyOptionCache (info); if (info->info) { GLuint 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); }}void driDestroyOptionCache (driOptionCache *cache) { if (cache->values) FREE (cache->values);}GLboolean driCheckOption (const driOptionCache *cache, const char *name, driOptionType type) { GLuint 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); /* 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); /* 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); /* 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -