📄 xmlconfig.c
字号:
abort(); } /* pass 2: parse all ranges into preallocated array */ range = cp; for (i = 0; i < nRanges; ++i) { XML_Char *end, *sep; assert (range); end = strchr (range, ','); if (end) *end = '\0'; sep = strchr (range, ':'); if (sep) { /* non-empty interval */ *sep = '\0'; if (!parseValue (&ranges[i].start, info->type, range) || !parseValue (&ranges[i].end, info->type, sep+1)) break; if (info->type == DRI_INT && ranges[i].start._int > ranges[i].end._int) break; if (info->type == DRI_FLOAT && ranges[i].start._float > ranges[i].end._float) break; } else { /* empty interval */ if (!parseValue (&ranges[i].start, info->type, range)) break; ranges[i].end = ranges[i].start; } if (end) range = end+1; else range = NULL; } FREE (cp); if (i < nRanges) { FREE (ranges); return GL_FALSE; } else assert (range == NULL); info->nRanges = nRanges; info->ranges = ranges; return GL_TRUE;}/** \brief Check if a value is in one of info->ranges. */static GLboolean checkValue (const driOptionValue *v, const driOptionInfo *info) { GLuint i; assert (info->type != DRI_BOOL); /* should be caught by the parser */ if (info->nRanges == 0) return GL_TRUE; switch (info->type) { case DRI_ENUM: /* enum is just a special integer */ case DRI_INT: for (i = 0; i < info->nRanges; ++i) if (v->_int >= info->ranges[i].start._int && v->_int <= info->ranges[i].end._int) return GL_TRUE; break; case DRI_FLOAT: for (i = 0; i < info->nRanges; ++i) if (v->_float >= info->ranges[i].start._float && v->_float <= info->ranges[i].end._float) return GL_TRUE; break; default: assert (0); /* should never happen */ } return GL_FALSE;}/** \brief Output a warning message. */#define XML_WARNING1(msg) do {\ __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \ (int) XML_GetCurrentLineNumber(data->parser), \ (int) XML_GetCurrentColumnNumber(data->parser)); \} while (0)#define XML_WARNING(msg,args...) do { \ __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \ (int) XML_GetCurrentLineNumber(data->parser), \ (int) XML_GetCurrentColumnNumber(data->parser), \ args); \} while (0)/** \brief Output an error message. */#define XML_ERROR1(msg) do { \ __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \ (int) XML_GetCurrentLineNumber(data->parser), \ (int) XML_GetCurrentColumnNumber(data->parser)); \} while (0)#define XML_ERROR(msg,args...) do { \ __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \ (int) XML_GetCurrentLineNumber(data->parser), \ (int) XML_GetCurrentColumnNumber(data->parser), \ args); \} while (0)/** \brief Output a fatal error message and abort. */#define XML_FATAL1(msg) do { \ fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \ data->name, \ (int) XML_GetCurrentLineNumber(data->parser), \ (int) XML_GetCurrentColumnNumber(data->parser)); \ abort();\} while (0)#define XML_FATAL(msg,args...) do { \ fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \ data->name, \ (int) XML_GetCurrentLineNumber(data->parser), \ (int) XML_GetCurrentColumnNumber(data->parser), \ args); \ abort();\} while (0)/** \brief Parser context for __driConfigOptions. */struct OptInfoData { const char *name; XML_Parser parser; driOptionCache *cache; GLboolean inDriInfo; GLboolean inSection; GLboolean inDesc; GLboolean inOption; GLboolean inEnum; int curOption;};/** \brief Elements in __driConfigOptions. */enum OptInfoElem { OI_DESCRIPTION = 0, OI_DRIINFO, OI_ENUM, OI_OPTION, OI_SECTION, OI_COUNT};static const XML_Char *OptInfoElems[] = { "description", "driinfo", "enum", "option", "section"};/** \brief Parse attributes of an enum element. * * We're not actually interested in the data. Just make sure this is ok * for external configuration tools. */static void parseEnumAttr (struct OptInfoData *data, const XML_Char **attr) { GLuint i; const XML_Char *value = NULL, *text = NULL; driOptionValue v; GLuint opt = data->curOption; for (i = 0; attr[i]; i += 2) { if (!strcmp (attr[i], "value")) value = attr[i+1]; else if (!strcmp (attr[i], "text")) text = attr[i+1]; else XML_FATAL("illegal enum attribute: %s.", attr[i]); } if (!value) XML_FATAL1 ("value attribute missing in enum."); if (!text) XML_FATAL1 ("text attribute missing in enum."); if (!parseValue (&v, data->cache->info[opt].type, value)) XML_FATAL ("illegal enum value: %s.", value); if (!checkValue (&v, &data->cache->info[opt])) XML_FATAL ("enum value out of valid range: %s.", value);}/** \brief Parse attributes of a description element. * * We're not actually interested in the data. Just make sure this is ok * for external configuration tools. */static void parseDescAttr (struct OptInfoData *data, const XML_Char **attr) { GLuint i; const XML_Char *lang = NULL, *text = NULL; for (i = 0; attr[i]; i += 2) { if (!strcmp (attr[i], "lang")) lang = attr[i+1]; else if (!strcmp (attr[i], "text")) text = attr[i+1]; else XML_FATAL("illegal description attribute: %s.", attr[i]); } if (!lang) XML_FATAL1 ("lang attribute missing in description."); if (!text) XML_FATAL1 ("text attribute missing in description.");}/** \brief Parse attributes of an option element. */static void parseOptInfoAttr (struct OptInfoData *data, const XML_Char **attr) { enum OptAttr {OA_DEFAULT = 0, OA_NAME, OA_TYPE, OA_VALID, OA_COUNT}; static const XML_Char *optAttr[] = {"default", "name", "type", "valid"}; const XML_Char *attrVal[OA_COUNT] = {NULL, NULL, NULL, NULL}; const char *defaultVal; driOptionCache *cache = data->cache; GLuint opt, i; for (i = 0; attr[i]; i += 2) { GLuint attrName = bsearchStr (attr[i], optAttr, OA_COUNT); if (attrName >= OA_COUNT) XML_FATAL ("illegal option attribute: %s", attr[i]); attrVal[attrName] = attr[i+1]; } if (!attrVal[OA_NAME]) XML_FATAL1 ("name attribute missing in option."); if (!attrVal[OA_TYPE]) XML_FATAL1 ("type attribute missing in option."); if (!attrVal[OA_DEFAULT]) XML_FATAL1 ("default attribute missing in option."); opt = findOption (cache, attrVal[OA_NAME]); if (cache->info[opt].name) XML_FATAL ("option %s redefined.", attrVal[OA_NAME]); data->curOption = opt; XSTRDUP (cache->info[opt].name, attrVal[OA_NAME]); if (!strcmp (attrVal[OA_TYPE], "bool")) cache->info[opt].type = DRI_BOOL; else if (!strcmp (attrVal[OA_TYPE], "enum")) cache->info[opt].type = DRI_ENUM; else if (!strcmp (attrVal[OA_TYPE], "int")) cache->info[opt].type = DRI_INT; else if (!strcmp (attrVal[OA_TYPE], "float")) cache->info[opt].type = DRI_FLOAT; else XML_FATAL ("illegal type in option: %s.", attrVal[OA_TYPE]); defaultVal = getenv (cache->info[opt].name); if (defaultVal != NULL) { /* don't use XML_WARNING, we want the user to see this! */ fprintf (stderr, "ATTENTION: default value of option %s overridden by environment.\n", cache->info[opt].name); } else defaultVal = attrVal[OA_DEFAULT]; if (!parseValue (&cache->values[opt], cache->info[opt].type, defaultVal)) XML_FATAL ("illegal default value: %s.", defaultVal); if (attrVal[OA_VALID]) { if (cache->info[opt].type == DRI_BOOL) XML_FATAL1 ("boolean option with valid attribute."); if (!parseRanges (&cache->info[opt], attrVal[OA_VALID])) XML_FATAL ("illegal valid attribute: %s.", attrVal[OA_VALID]); if (!checkValue (&cache->values[opt], &cache->info[opt])) XML_FATAL ("default value out of valid range '%s': %s.", attrVal[OA_VALID], defaultVal); } else if (cache->info[opt].type == DRI_ENUM) { XML_FATAL1 ("valid attribute missing in option (mandatory for enums)."); } else { cache->info[opt].nRanges = 0; cache->info[opt].ranges = NULL; }}/** \brief Handler for start element events. */static void optInfoStartElem (void *userData, const XML_Char *name, const XML_Char **attr) { struct OptInfoData *data = (struct OptInfoData *)userData; enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT); switch (elem) { case OI_DRIINFO: if (data->inDriInfo) XML_FATAL1 ("nested <driinfo> elements."); if (attr[0]) XML_FATAL1 ("attributes specified on <driinfo> element."); data->inDriInfo = GL_TRUE; break; case OI_SECTION: if (!data->inDriInfo) XML_FATAL1 ("<section> must be inside <driinfo>."); if (data->inSection) XML_FATAL1 ("nested <section> elements."); if (attr[0]) XML_FATAL1 ("attributes specified on <section> element."); data->inSection = GL_TRUE; break; case OI_DESCRIPTION: if (!data->inSection && !data->inOption) XML_FATAL1 ("<description> must be inside <description> or <option."); if (data->inDesc) XML_FATAL1 ("nested <description> elements."); data->inDesc = GL_TRUE; parseDescAttr (data, attr); break; case OI_OPTION: if (!data->inSection) XML_FATAL1 ("<option> must be inside <section>."); if (data->inDesc) XML_FATAL1 ("<option> nested in <description> element."); if (data->inOption) XML_FATAL1 ("nested <option> elements."); data->inOption = GL_TRUE; parseOptInfoAttr (data, attr); break; case OI_ENUM: if (!(data->inOption && data->inDesc)) XML_FATAL1 ("<enum> must be inside <option> and <description>."); if (data->inEnum) XML_FATAL1 ("nested <enum> elements."); data->inEnum = GL_TRUE; parseEnumAttr (data, attr); break; default: XML_FATAL ("unknown element: %s.", name); }}/** \brief Handler for end element events. */static void optInfoEndElem (void *userData, const XML_Char *name) { struct OptInfoData *data = (struct OptInfoData *)userData; enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT); switch (elem) { case OI_DRIINFO: data->inDriInfo = GL_FALSE; break; case OI_SECTION: data->inSection = GL_FALSE; break; case OI_DESCRIPTION: data->inDesc = GL_FALSE; break; case OI_OPTION: data->inOption = GL_FALSE; break; case OI_ENUM: data->inEnum = GL_FALSE; break; default: assert (0); /* should have been caught by StartElem */ }}void driParseOptionInfo (driOptionCache *info, const char *configOptions, GLuint nConfigOptions) { XML_Parser p; int status; struct OptInfoData userData; struct OptInfoData *data = &userData; GLuint realNoptions; /* determine hash table size and allocate memory: * 3/2 of the number of options, rounded up, so there remains always * at least one free entry. This is needed for detecting undefined * options in configuration files without getting a hash table overflow. * Round this up to a power of two. */ GLuint minSize = (nConfigOptions*3 + 1) / 2; GLuint size, log2size; for (size = 1, log2size = 0; size < minSize; size <<= 1, ++log2size); info->tableSize = log2size; info->info = CALLOC (size * sizeof (driOptionInfo)); info->values = CALLOC (size * sizeof (driOptionValue)); if (info->info == NULL || info->values == NULL) { fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); abort(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -