fcxml.c revision a6844aab
12c393a42Smrg/* 2a6844aabSmrg * fontconfig/src/fcxml.c 32c393a42Smrg * 42c393a42Smrg * Copyright © 2002 Keith Packard 52c393a42Smrg * 62c393a42Smrg * Permission to use, copy, modify, distribute, and sell this software and its 72c393a42Smrg * documentation for any purpose is hereby granted without fee, provided that 82c393a42Smrg * the above copyright notice appear in all copies and that both that 92c393a42Smrg * copyright notice and this permission notice appear in supporting 102c393a42Smrg * documentation, and that the name of Keith Packard not be used in 112c393a42Smrg * advertising or publicity pertaining to distribution of the software without 122c393a42Smrg * specific, written prior permission. Keith Packard makes no 132c393a42Smrg * representations about the suitability of this software for any purpose. It 142c393a42Smrg * is provided "as is" without express or implied warranty. 152c393a42Smrg * 16a6844aabSmrg * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 172c393a42Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18a6844aabSmrg * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR 192c393a42Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 202c393a42Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 212c393a42Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 222c393a42Smrg * PERFORMANCE OF THIS SOFTWARE. 232c393a42Smrg */ 242c393a42Smrg 252c393a42Smrg#include "fcint.h" 262c393a42Smrg#include <fcntl.h> 272c393a42Smrg#include <stdarg.h> 282c393a42Smrg#include <dirent.h> 292c393a42Smrg 302c393a42Smrg#ifdef ENABLE_LIBXML2 312c393a42Smrg 322c393a42Smrg#include <libxml/parser.h> 332c393a42Smrg 342c393a42Smrg#define XML_Char xmlChar 352c393a42Smrg#define XML_Parser xmlParserCtxtPtr 362c393a42Smrg#define XML_ParserFree xmlFreeParserCtxt 372c393a42Smrg#define XML_GetCurrentLineNumber xmlSAX2GetLineNumber 382c393a42Smrg#define XML_GetErrorCode xmlCtxtGetLastError 392c393a42Smrg#define XML_ErrorString(Error) (Error)->message 402c393a42Smrg 412c393a42Smrg#else /* ENABLE_LIBXML2 */ 422c393a42Smrg 432c393a42Smrg#ifndef HAVE_XMLPARSE_H 442c393a42Smrg#define HAVE_XMLPARSE_H 0 452c393a42Smrg#endif 462c393a42Smrg 472c393a42Smrg#if HAVE_XMLPARSE_H 482c393a42Smrg#include <xmlparse.h> 492c393a42Smrg#else 502c393a42Smrg#include <expat.h> 512c393a42Smrg#endif 522c393a42Smrg 532c393a42Smrg#endif /* ENABLE_LIBXML2 */ 542c393a42Smrg 552c393a42Smrg#ifdef _WIN32 56a6844aabSmrg#define _WIN32_WINNT 0x0500 572c393a42Smrg#define STRICT 582c393a42Smrg#include <windows.h> 592c393a42Smrg#undef STRICT 60a6844aabSmrg#include <mbstring.h> 612c393a42Smrg#endif 622c393a42Smrg 63a6844aabSmrgstatic void 64a6844aabSmrgFcExprDestroy (FcExpr *e); 652c393a42Smrg 662c393a42Smrgvoid 672c393a42SmrgFcTestDestroy (FcTest *test) 682c393a42Smrg{ 692c393a42Smrg if (test->next) 702c393a42Smrg FcTestDestroy (test->next); 712c393a42Smrg FcExprDestroy (test->expr); 722c393a42Smrg FcMemFree (FC_MEM_TEST, sizeof (FcTest)); 732c393a42Smrg free (test); 742c393a42Smrg} 752c393a42Smrg 76a6844aabSmrgstatic FcExpr * 77a6844aabSmrgFcExprCreateInteger (FcConfig *config, int i) 782c393a42Smrg{ 79a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 802c393a42Smrg if (e) 812c393a42Smrg { 822c393a42Smrg e->op = FcOpInteger; 832c393a42Smrg e->u.ival = i; 842c393a42Smrg } 852c393a42Smrg return e; 862c393a42Smrg} 872c393a42Smrg 88a6844aabSmrgstatic FcExpr * 89a6844aabSmrgFcExprCreateDouble (FcConfig *config, double d) 902c393a42Smrg{ 91a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 922c393a42Smrg if (e) 932c393a42Smrg { 942c393a42Smrg e->op = FcOpDouble; 952c393a42Smrg e->u.dval = d; 962c393a42Smrg } 972c393a42Smrg return e; 982c393a42Smrg} 992c393a42Smrg 100a6844aabSmrgstatic FcExpr * 101a6844aabSmrgFcExprCreateString (FcConfig *config, const FcChar8 *s) 1022c393a42Smrg{ 103a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 1042c393a42Smrg if (e) 1052c393a42Smrg { 1062c393a42Smrg e->op = FcOpString; 107a6844aabSmrg e->u.sval = FcStrStaticName (s); 1082c393a42Smrg } 1092c393a42Smrg return e; 1102c393a42Smrg} 1112c393a42Smrg 112a6844aabSmrgstatic FcExpr * 113a6844aabSmrgFcExprCreateMatrix (FcConfig *config, const FcMatrix *m) 1142c393a42Smrg{ 115a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 1162c393a42Smrg if (e) 1172c393a42Smrg { 1182c393a42Smrg e->op = FcOpMatrix; 1192c393a42Smrg e->u.mval = FcMatrixCopy (m); 1202c393a42Smrg } 1212c393a42Smrg return e; 1222c393a42Smrg} 1232c393a42Smrg 124a6844aabSmrgstatic FcExpr * 125a6844aabSmrgFcExprCreateBool (FcConfig *config, FcBool b) 1262c393a42Smrg{ 127a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 1282c393a42Smrg if (e) 1292c393a42Smrg { 1302c393a42Smrg e->op = FcOpBool; 1312c393a42Smrg e->u.bval = b; 1322c393a42Smrg } 1332c393a42Smrg return e; 1342c393a42Smrg} 1352c393a42Smrg 136a6844aabSmrgstatic FcExpr * 137a6844aabSmrgFcExprCreateField (FcConfig *config, const char *field) 1382c393a42Smrg{ 139a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 1402c393a42Smrg if (e) 1412c393a42Smrg { 1422c393a42Smrg e->op = FcOpField; 1432c393a42Smrg e->u.object = FcObjectFromName (field); 1442c393a42Smrg } 1452c393a42Smrg return e; 1462c393a42Smrg} 1472c393a42Smrg 148a6844aabSmrgstatic FcExpr * 149a6844aabSmrgFcExprCreateConst (FcConfig *config, const FcChar8 *constant) 1502c393a42Smrg{ 151a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 1522c393a42Smrg if (e) 1532c393a42Smrg { 1542c393a42Smrg e->op = FcOpConst; 155a6844aabSmrg e->u.constant = FcStrStaticName (constant); 1562c393a42Smrg } 1572c393a42Smrg return e; 1582c393a42Smrg} 1592c393a42Smrg 160a6844aabSmrgstatic FcExpr * 161a6844aabSmrgFcExprCreateOp (FcConfig *config, FcExpr *left, FcOp op, FcExpr *right) 1622c393a42Smrg{ 163a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 1642c393a42Smrg if (e) 1652c393a42Smrg { 1662c393a42Smrg e->op = op; 1672c393a42Smrg e->u.tree.left = left; 1682c393a42Smrg e->u.tree.right = right; 1692c393a42Smrg } 1702c393a42Smrg return e; 1712c393a42Smrg} 1722c393a42Smrg 173a6844aabSmrgstatic void 1742c393a42SmrgFcExprDestroy (FcExpr *e) 1752c393a42Smrg{ 1762c393a42Smrg if (!e) 1772c393a42Smrg return; 1782c393a42Smrg switch (e->op) { 1792c393a42Smrg case FcOpInteger: 1802c393a42Smrg break; 1812c393a42Smrg case FcOpDouble: 1822c393a42Smrg break; 1832c393a42Smrg case FcOpString: 1842c393a42Smrg break; 1852c393a42Smrg case FcOpMatrix: 1862c393a42Smrg FcMatrixFree (e->u.mval); 1872c393a42Smrg break; 1882c393a42Smrg case FcOpCharSet: 1892c393a42Smrg FcCharSetDestroy (e->u.cval); 1902c393a42Smrg break; 1912c393a42Smrg case FcOpBool: 1922c393a42Smrg break; 1932c393a42Smrg case FcOpField: 1942c393a42Smrg break; 1952c393a42Smrg case FcOpConst: 1962c393a42Smrg break; 1972c393a42Smrg case FcOpAssign: 1982c393a42Smrg case FcOpAssignReplace: 1992c393a42Smrg case FcOpPrepend: 2002c393a42Smrg case FcOpPrependFirst: 2012c393a42Smrg case FcOpAppend: 2022c393a42Smrg case FcOpAppendLast: 2032c393a42Smrg break; 2042c393a42Smrg case FcOpOr: 2052c393a42Smrg case FcOpAnd: 2062c393a42Smrg case FcOpEqual: 2072c393a42Smrg case FcOpNotEqual: 2082c393a42Smrg case FcOpLess: 2092c393a42Smrg case FcOpLessEqual: 2102c393a42Smrg case FcOpMore: 2112c393a42Smrg case FcOpMoreEqual: 2122c393a42Smrg case FcOpContains: 2132c393a42Smrg case FcOpListing: 2142c393a42Smrg case FcOpNotContains: 2152c393a42Smrg case FcOpPlus: 2162c393a42Smrg case FcOpMinus: 2172c393a42Smrg case FcOpTimes: 2182c393a42Smrg case FcOpDivide: 2192c393a42Smrg case FcOpQuest: 2202c393a42Smrg case FcOpComma: 2212c393a42Smrg FcExprDestroy (e->u.tree.right); 2222c393a42Smrg /* fall through */ 2232c393a42Smrg case FcOpNot: 2242c393a42Smrg case FcOpFloor: 2252c393a42Smrg case FcOpCeil: 2262c393a42Smrg case FcOpRound: 2272c393a42Smrg case FcOpTrunc: 2282c393a42Smrg FcExprDestroy (e->u.tree.left); 2292c393a42Smrg break; 2302c393a42Smrg case FcOpNil: 2312c393a42Smrg case FcOpInvalid: 2322c393a42Smrg break; 2332c393a42Smrg } 234a6844aabSmrg 235a6844aabSmrg e->op = FcOpNil; 2362c393a42Smrg} 2372c393a42Smrg 2382c393a42Smrgvoid 2392c393a42SmrgFcEditDestroy (FcEdit *e) 2402c393a42Smrg{ 2412c393a42Smrg if (e->next) 2422c393a42Smrg FcEditDestroy (e->next); 2432c393a42Smrg if (e->expr) 2442c393a42Smrg FcExprDestroy (e->expr); 2452c393a42Smrg free (e); 2462c393a42Smrg} 2472c393a42Smrg 2482c393a42Smrgtypedef enum _FcElement { 2492c393a42Smrg FcElementNone, 2502c393a42Smrg FcElementFontconfig, 2512c393a42Smrg FcElementDir, 2522c393a42Smrg FcElementCacheDir, 2532c393a42Smrg FcElementCache, 2542c393a42Smrg FcElementInclude, 2552c393a42Smrg FcElementConfig, 2562c393a42Smrg FcElementMatch, 2572c393a42Smrg FcElementAlias, 2582c393a42Smrg 2592c393a42Smrg FcElementBlank, 2602c393a42Smrg FcElementRescan, 2612c393a42Smrg 2622c393a42Smrg FcElementPrefer, 2632c393a42Smrg FcElementAccept, 2642c393a42Smrg FcElementDefault, 2652c393a42Smrg FcElementFamily, 2662c393a42Smrg 2672c393a42Smrg FcElementSelectfont, 2682c393a42Smrg FcElementAcceptfont, 2692c393a42Smrg FcElementRejectfont, 2702c393a42Smrg FcElementGlob, 2712c393a42Smrg FcElementPattern, 2722c393a42Smrg FcElementPatelt, 2732c393a42Smrg 2742c393a42Smrg FcElementTest, 2752c393a42Smrg FcElementEdit, 2762c393a42Smrg FcElementInt, 2772c393a42Smrg FcElementDouble, 2782c393a42Smrg FcElementString, 2792c393a42Smrg FcElementMatrix, 2802c393a42Smrg FcElementBool, 2812c393a42Smrg FcElementCharset, 2822c393a42Smrg FcElementName, 2832c393a42Smrg FcElementConst, 2842c393a42Smrg FcElementOr, 2852c393a42Smrg FcElementAnd, 2862c393a42Smrg FcElementEq, 2872c393a42Smrg FcElementNotEq, 2882c393a42Smrg FcElementLess, 2892c393a42Smrg FcElementLessEq, 2902c393a42Smrg FcElementMore, 2912c393a42Smrg FcElementMoreEq, 2922c393a42Smrg FcElementContains, 2932c393a42Smrg FcElementNotContains, 2942c393a42Smrg FcElementPlus, 2952c393a42Smrg FcElementMinus, 2962c393a42Smrg FcElementTimes, 2972c393a42Smrg FcElementDivide, 2982c393a42Smrg FcElementNot, 2992c393a42Smrg FcElementIf, 3002c393a42Smrg FcElementFloor, 3012c393a42Smrg FcElementCeil, 3022c393a42Smrg FcElementRound, 3032c393a42Smrg FcElementTrunc, 3042c393a42Smrg FcElementUnknown 3052c393a42Smrg} FcElement; 3062c393a42Smrg 3072c393a42Smrgstatic const struct { 3082c393a42Smrg const char name[16]; 3092c393a42Smrg FcElement element; 3102c393a42Smrg} fcElementMap[] = { 3112c393a42Smrg { "fontconfig", FcElementFontconfig }, 3122c393a42Smrg { "dir", FcElementDir }, 3132c393a42Smrg { "cachedir", FcElementCacheDir }, 3142c393a42Smrg { "cache", FcElementCache }, 3152c393a42Smrg { "include", FcElementInclude }, 3162c393a42Smrg { "config", FcElementConfig }, 3172c393a42Smrg { "match", FcElementMatch }, 3182c393a42Smrg { "alias", FcElementAlias }, 3192c393a42Smrg 3202c393a42Smrg { "blank", FcElementBlank }, 3212c393a42Smrg { "rescan", FcElementRescan }, 3222c393a42Smrg 3232c393a42Smrg { "prefer", FcElementPrefer }, 3242c393a42Smrg { "accept", FcElementAccept }, 3252c393a42Smrg { "default", FcElementDefault }, 3262c393a42Smrg { "family", FcElementFamily }, 3272c393a42Smrg 3282c393a42Smrg { "selectfont", FcElementSelectfont }, 3292c393a42Smrg { "acceptfont", FcElementAcceptfont }, 3302c393a42Smrg { "rejectfont", FcElementRejectfont }, 3312c393a42Smrg { "glob", FcElementGlob }, 3322c393a42Smrg { "pattern", FcElementPattern }, 3332c393a42Smrg { "patelt", FcElementPatelt }, 3342c393a42Smrg 3352c393a42Smrg { "test", FcElementTest }, 3362c393a42Smrg { "edit", FcElementEdit }, 3372c393a42Smrg { "int", FcElementInt }, 3382c393a42Smrg { "double", FcElementDouble }, 3392c393a42Smrg { "string", FcElementString }, 3402c393a42Smrg { "matrix", FcElementMatrix }, 3412c393a42Smrg { "bool", FcElementBool }, 3422c393a42Smrg { "charset", FcElementCharset }, 3432c393a42Smrg { "name", FcElementName }, 3442c393a42Smrg { "const", FcElementConst }, 3452c393a42Smrg { "or", FcElementOr }, 3462c393a42Smrg { "and", FcElementAnd }, 3472c393a42Smrg { "eq", FcElementEq }, 3482c393a42Smrg { "not_eq", FcElementNotEq }, 3492c393a42Smrg { "less", FcElementLess }, 3502c393a42Smrg { "less_eq", FcElementLessEq }, 3512c393a42Smrg { "more", FcElementMore }, 3522c393a42Smrg { "more_eq", FcElementMoreEq }, 3532c393a42Smrg { "contains", FcElementContains }, 3542c393a42Smrg { "not_contains", FcElementNotContains }, 3552c393a42Smrg { "plus", FcElementPlus }, 3562c393a42Smrg { "minus", FcElementMinus }, 3572c393a42Smrg { "times", FcElementTimes }, 3582c393a42Smrg { "divide", FcElementDivide }, 3592c393a42Smrg { "not", FcElementNot }, 3602c393a42Smrg { "if", FcElementIf }, 3612c393a42Smrg { "floor", FcElementFloor }, 3622c393a42Smrg { "ceil", FcElementCeil }, 3632c393a42Smrg { "round", FcElementRound }, 3642c393a42Smrg { "trunc", FcElementTrunc }, 3652c393a42Smrg}; 3662c393a42Smrg#define NUM_ELEMENT_MAPS (int) (sizeof fcElementMap / sizeof fcElementMap[0]) 3672c393a42Smrg 3682c393a42Smrgstatic FcElement 3692c393a42SmrgFcElementMap (const XML_Char *name) 3702c393a42Smrg{ 3712c393a42Smrg 3722c393a42Smrg int i; 3732c393a42Smrg for (i = 0; i < NUM_ELEMENT_MAPS; i++) 3742c393a42Smrg if (!strcmp ((char *) name, fcElementMap[i].name)) 3752c393a42Smrg return fcElementMap[i].element; 3762c393a42Smrg return FcElementUnknown; 3772c393a42Smrg} 3782c393a42Smrg 3792c393a42Smrgtypedef struct _FcPStack { 3802c393a42Smrg struct _FcPStack *prev; 3812c393a42Smrg FcElement element; 3822c393a42Smrg FcChar8 **attr; 3832c393a42Smrg FcStrBuf str; 384a6844aabSmrg FcChar8 *attr_buf_static[16]; 3852c393a42Smrg} FcPStack; 3862c393a42Smrg 3872c393a42Smrgtypedef enum _FcVStackTag { 3882c393a42Smrg FcVStackNone, 3892c393a42Smrg 3902c393a42Smrg FcVStackString, 3912c393a42Smrg FcVStackFamily, 3922c393a42Smrg FcVStackField, 3932c393a42Smrg FcVStackConstant, 3942c393a42Smrg FcVStackGlob, 3952c393a42Smrg FcVStackPattern, 3962c393a42Smrg 3972c393a42Smrg FcVStackPrefer, 3982c393a42Smrg FcVStackAccept, 3992c393a42Smrg FcVStackDefault, 4002c393a42Smrg 4012c393a42Smrg FcVStackInteger, 4022c393a42Smrg FcVStackDouble, 4032c393a42Smrg FcVStackMatrix, 4042c393a42Smrg FcVStackBool, 4052c393a42Smrg 4062c393a42Smrg FcVStackTest, 4072c393a42Smrg FcVStackExpr, 4082c393a42Smrg FcVStackEdit 4092c393a42Smrg} FcVStackTag; 4102c393a42Smrg 4112c393a42Smrgtypedef struct _FcVStack { 4122c393a42Smrg struct _FcVStack *prev; 4132c393a42Smrg FcPStack *pstack; /* related parse element */ 4142c393a42Smrg FcVStackTag tag; 4152c393a42Smrg union { 4162c393a42Smrg FcChar8 *string; 4172c393a42Smrg 4182c393a42Smrg int integer; 4192c393a42Smrg double _double; 4202c393a42Smrg FcMatrix *matrix; 421a6844aabSmrg FcBool bool_; 4222c393a42Smrg 4232c393a42Smrg FcTest *test; 4242c393a42Smrg FcQual qual; 4252c393a42Smrg FcOp op; 4262c393a42Smrg FcExpr *expr; 4272c393a42Smrg FcEdit *edit; 4282c393a42Smrg 4292c393a42Smrg FcPattern *pattern; 4302c393a42Smrg } u; 4312c393a42Smrg} FcVStack; 4322c393a42Smrg 4332c393a42Smrgtypedef struct _FcConfigParse { 4342c393a42Smrg FcPStack *pstack; 4352c393a42Smrg FcVStack *vstack; 4362c393a42Smrg FcBool error; 4372c393a42Smrg const FcChar8 *name; 4382c393a42Smrg FcConfig *config; 4392c393a42Smrg XML_Parser parser; 440a6844aabSmrg int pstack_static_used; 441a6844aabSmrg FcPStack pstack_static[8]; 442a6844aabSmrg int vstack_static_used; 443a6844aabSmrg FcVStack vstack_static[64]; 4442c393a42Smrg} FcConfigParse; 4452c393a42Smrg 4462c393a42Smrgtypedef enum _FcConfigSeverity { 4472c393a42Smrg FcSevereInfo, FcSevereWarning, FcSevereError 4482c393a42Smrg} FcConfigSeverity; 4492c393a42Smrg 4502c393a42Smrgstatic void 4512c393a42SmrgFcConfigMessage (FcConfigParse *parse, FcConfigSeverity severe, const char *fmt, ...) 4522c393a42Smrg{ 4532c393a42Smrg const char *s = "unknown"; 4542c393a42Smrg va_list args; 4552c393a42Smrg 4562c393a42Smrg va_start (args, fmt); 4572c393a42Smrg 4582c393a42Smrg switch (severe) { 4592c393a42Smrg case FcSevereInfo: s = "info"; break; 4602c393a42Smrg case FcSevereWarning: s = "warning"; break; 4612c393a42Smrg case FcSevereError: s = "error"; break; 4622c393a42Smrg } 4632c393a42Smrg if (parse) 4642c393a42Smrg { 4652c393a42Smrg if (parse->name) 4662c393a42Smrg fprintf (stderr, "Fontconfig %s: \"%s\", line %d: ", s, 4672c393a42Smrg parse->name, (int)XML_GetCurrentLineNumber (parse->parser)); 4682c393a42Smrg else 4692c393a42Smrg fprintf (stderr, "Fontconfig %s: line %d: ", s, 4702c393a42Smrg (int)XML_GetCurrentLineNumber (parse->parser)); 4712c393a42Smrg if (severe >= FcSevereError) 4722c393a42Smrg parse->error = FcTrue; 4732c393a42Smrg } 4742c393a42Smrg else 4752c393a42Smrg fprintf (stderr, "Fontconfig %s: ", s); 4762c393a42Smrg vfprintf (stderr, fmt, args); 4772c393a42Smrg fprintf (stderr, "\n"); 4782c393a42Smrg va_end (args); 4792c393a42Smrg} 4802c393a42Smrg 4812c393a42Smrg 4822c393a42Smrgstatic const char * 4832c393a42SmrgFcTypeName (FcType type) 4842c393a42Smrg{ 4852c393a42Smrg switch (type) { 4862c393a42Smrg case FcTypeVoid: 4872c393a42Smrg return "void"; 4882c393a42Smrg case FcTypeInteger: 4892c393a42Smrg case FcTypeDouble: 4902c393a42Smrg return "number"; 4912c393a42Smrg case FcTypeString: 4922c393a42Smrg return "string"; 4932c393a42Smrg case FcTypeBool: 4942c393a42Smrg return "bool"; 4952c393a42Smrg case FcTypeMatrix: 4962c393a42Smrg return "matrix"; 4972c393a42Smrg case FcTypeCharSet: 4982c393a42Smrg return "charset"; 4992c393a42Smrg case FcTypeFTFace: 5002c393a42Smrg return "FT_Face"; 5012c393a42Smrg case FcTypeLangSet: 5022c393a42Smrg return "langset"; 5032c393a42Smrg default: 5042c393a42Smrg return "unknown"; 5052c393a42Smrg } 5062c393a42Smrg} 5072c393a42Smrg 5082c393a42Smrgstatic void 5092c393a42SmrgFcTypecheckValue (FcConfigParse *parse, FcType value, FcType type) 5102c393a42Smrg{ 5112c393a42Smrg if (value == FcTypeInteger) 5122c393a42Smrg value = FcTypeDouble; 5132c393a42Smrg if (type == FcTypeInteger) 5142c393a42Smrg type = FcTypeDouble; 5152c393a42Smrg if (value != type) 5162c393a42Smrg { 5172c393a42Smrg if ((value == FcTypeLangSet && type == FcTypeString) || 5182c393a42Smrg (value == FcTypeString && type == FcTypeLangSet)) 5192c393a42Smrg return; 5202c393a42Smrg if (type == (FcType) -1) 5212c393a42Smrg return; 5222c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "saw %s, expected %s", 5232c393a42Smrg FcTypeName (value), FcTypeName (type)); 5242c393a42Smrg } 5252c393a42Smrg} 5262c393a42Smrg 5272c393a42Smrgstatic void 5282c393a42SmrgFcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type) 5292c393a42Smrg{ 5302c393a42Smrg const FcObjectType *o; 5312c393a42Smrg const FcConstant *c; 5322c393a42Smrg 5332c393a42Smrg /* If parsing the expression failed, some nodes may be NULL */ 5342c393a42Smrg if (!expr) 5352c393a42Smrg return; 5362c393a42Smrg 5372c393a42Smrg switch (expr->op) { 5382c393a42Smrg case FcOpInteger: 5392c393a42Smrg case FcOpDouble: 5402c393a42Smrg FcTypecheckValue (parse, FcTypeDouble, type); 5412c393a42Smrg break; 5422c393a42Smrg case FcOpString: 5432c393a42Smrg FcTypecheckValue (parse, FcTypeString, type); 5442c393a42Smrg break; 5452c393a42Smrg case FcOpMatrix: 5462c393a42Smrg FcTypecheckValue (parse, FcTypeMatrix, type); 5472c393a42Smrg break; 5482c393a42Smrg case FcOpBool: 5492c393a42Smrg FcTypecheckValue (parse, FcTypeBool, type); 5502c393a42Smrg break; 5512c393a42Smrg case FcOpCharSet: 5522c393a42Smrg FcTypecheckValue (parse, FcTypeCharSet, type); 5532c393a42Smrg break; 5542c393a42Smrg case FcOpNil: 5552c393a42Smrg break; 5562c393a42Smrg case FcOpField: 5572c393a42Smrg o = FcNameGetObjectType (FcObjectName (expr->u.object)); 5582c393a42Smrg if (o) 5592c393a42Smrg FcTypecheckValue (parse, o->type, type); 5602c393a42Smrg break; 5612c393a42Smrg case FcOpConst: 5622c393a42Smrg c = FcNameGetConstant (expr->u.constant); 5632c393a42Smrg if (c) 5642c393a42Smrg { 5652c393a42Smrg o = FcNameGetObjectType (c->object); 5662c393a42Smrg if (o) 5672c393a42Smrg FcTypecheckValue (parse, o->type, type); 5682c393a42Smrg } 5692c393a42Smrg else 5702c393a42Smrg FcConfigMessage (parse, FcSevereWarning, 5712c393a42Smrg "invalid constant used : %s", 5722c393a42Smrg expr->u.constant); 5732c393a42Smrg break; 5742c393a42Smrg case FcOpQuest: 5752c393a42Smrg FcTypecheckExpr (parse, expr->u.tree.left, FcTypeBool); 5762c393a42Smrg FcTypecheckExpr (parse, expr->u.tree.right->u.tree.left, type); 5772c393a42Smrg FcTypecheckExpr (parse, expr->u.tree.right->u.tree.right, type); 5782c393a42Smrg break; 5792c393a42Smrg case FcOpAssign: 5802c393a42Smrg case FcOpAssignReplace: 5812c393a42Smrg break; 5822c393a42Smrg case FcOpEqual: 5832c393a42Smrg case FcOpNotEqual: 5842c393a42Smrg case FcOpLess: 5852c393a42Smrg case FcOpLessEqual: 5862c393a42Smrg case FcOpMore: 5872c393a42Smrg case FcOpMoreEqual: 5882c393a42Smrg case FcOpContains: 5892c393a42Smrg case FcOpNotContains: 5902c393a42Smrg case FcOpListing: 5912c393a42Smrg FcTypecheckValue (parse, FcTypeBool, type); 5922c393a42Smrg break; 5932c393a42Smrg case FcOpComma: 5942c393a42Smrg case FcOpOr: 5952c393a42Smrg case FcOpAnd: 5962c393a42Smrg case FcOpPlus: 5972c393a42Smrg case FcOpMinus: 5982c393a42Smrg case FcOpTimes: 5992c393a42Smrg case FcOpDivide: 6002c393a42Smrg FcTypecheckExpr (parse, expr->u.tree.left, type); 6012c393a42Smrg FcTypecheckExpr (parse, expr->u.tree.right, type); 6022c393a42Smrg break; 6032c393a42Smrg case FcOpNot: 6042c393a42Smrg FcTypecheckValue (parse, FcTypeBool, type); 6052c393a42Smrg FcTypecheckExpr (parse, expr->u.tree.left, FcTypeBool); 6062c393a42Smrg break; 6072c393a42Smrg case FcOpFloor: 6082c393a42Smrg case FcOpCeil: 6092c393a42Smrg case FcOpRound: 6102c393a42Smrg case FcOpTrunc: 6112c393a42Smrg FcTypecheckValue (parse, FcTypeDouble, type); 6122c393a42Smrg FcTypecheckExpr (parse, expr->u.tree.left, FcTypeDouble); 6132c393a42Smrg break; 6142c393a42Smrg default: 6152c393a42Smrg break; 6162c393a42Smrg } 6172c393a42Smrg} 6182c393a42Smrg 6192c393a42Smrgstatic FcTest * 6202c393a42SmrgFcTestCreate (FcConfigParse *parse, 6212c393a42Smrg FcMatchKind kind, 6222c393a42Smrg FcQual qual, 6232c393a42Smrg const FcChar8 *field, 6242c393a42Smrg FcOp compare, 6252c393a42Smrg FcExpr *expr) 6262c393a42Smrg{ 6272c393a42Smrg FcTest *test = (FcTest *) malloc (sizeof (FcTest)); 6282c393a42Smrg 6292c393a42Smrg if (test) 6302c393a42Smrg { 6312c393a42Smrg const FcObjectType *o; 6322c393a42Smrg 6332c393a42Smrg FcMemAlloc (FC_MEM_TEST, sizeof (FcTest)); 6342c393a42Smrg test->next = 0; 6352c393a42Smrg test->kind = kind; 6362c393a42Smrg test->qual = qual; 6372c393a42Smrg test->object = FcObjectFromName ((const char *) field); 6382c393a42Smrg test->op = compare; 6392c393a42Smrg test->expr = expr; 6402c393a42Smrg o = FcNameGetObjectType (FcObjectName (test->object)); 6412c393a42Smrg if (o) 6422c393a42Smrg FcTypecheckExpr (parse, expr, o->type); 6432c393a42Smrg } 6442c393a42Smrg return test; 6452c393a42Smrg} 6462c393a42Smrg 6472c393a42Smrgstatic FcEdit * 6482c393a42SmrgFcEditCreate (FcConfigParse *parse, 6492c393a42Smrg FcObject object, 6502c393a42Smrg FcOp op, 6512c393a42Smrg FcExpr *expr, 6522c393a42Smrg FcValueBinding binding) 6532c393a42Smrg{ 6542c393a42Smrg FcEdit *e = (FcEdit *) malloc (sizeof (FcEdit)); 6552c393a42Smrg 6562c393a42Smrg if (e) 6572c393a42Smrg { 6582c393a42Smrg const FcObjectType *o; 6592c393a42Smrg 6602c393a42Smrg e->next = 0; 6612c393a42Smrg e->object = object; 6622c393a42Smrg e->op = op; 6632c393a42Smrg e->expr = expr; 6642c393a42Smrg e->binding = binding; 6652c393a42Smrg o = FcNameGetObjectType (FcObjectName (e->object)); 6662c393a42Smrg if (o) 6672c393a42Smrg FcTypecheckExpr (parse, expr, o->type); 6682c393a42Smrg } 6692c393a42Smrg return e; 6702c393a42Smrg} 6712c393a42Smrg 6722c393a42Smrgstatic FcVStack * 673a6844aabSmrgFcVStackCreateAndPush (FcConfigParse *parse) 6742c393a42Smrg{ 6752c393a42Smrg FcVStack *new; 6762c393a42Smrg 677a6844aabSmrg if (parse->vstack_static_used < sizeof (parse->vstack_static) / sizeof (parse->vstack_static[0])) 678a6844aabSmrg new = &parse->vstack_static[parse->vstack_static_used++]; 679a6844aabSmrg else 680a6844aabSmrg { 681a6844aabSmrg new = malloc (sizeof (FcVStack)); 682a6844aabSmrg if (!new) 683a6844aabSmrg return 0; 684a6844aabSmrg FcMemAlloc (FC_MEM_VSTACK, sizeof (FcVStack)); 685a6844aabSmrg } 6862c393a42Smrg new->tag = FcVStackNone; 6872c393a42Smrg new->prev = 0; 6882c393a42Smrg 689a6844aabSmrg new->prev = parse->vstack; 690a6844aabSmrg new->pstack = parse->pstack ? parse->pstack->prev : 0; 691a6844aabSmrg parse->vstack = new; 6922c393a42Smrg 693a6844aabSmrg return new; 6942c393a42Smrg} 6952c393a42Smrg 6962c393a42Smrgstatic FcBool 6972c393a42SmrgFcVStackPushString (FcConfigParse *parse, FcVStackTag tag, FcChar8 *string) 6982c393a42Smrg{ 699a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 7002c393a42Smrg if (!vstack) 7012c393a42Smrg return FcFalse; 7022c393a42Smrg vstack->u.string = string; 7032c393a42Smrg vstack->tag = tag; 7042c393a42Smrg return FcTrue; 7052c393a42Smrg} 7062c393a42Smrg 7072c393a42Smrgstatic FcBool 7082c393a42SmrgFcVStackPushInteger (FcConfigParse *parse, int integer) 7092c393a42Smrg{ 710a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 7112c393a42Smrg if (!vstack) 7122c393a42Smrg return FcFalse; 7132c393a42Smrg vstack->u.integer = integer; 7142c393a42Smrg vstack->tag = FcVStackInteger; 7152c393a42Smrg return FcTrue; 7162c393a42Smrg} 7172c393a42Smrg 7182c393a42Smrgstatic FcBool 7192c393a42SmrgFcVStackPushDouble (FcConfigParse *parse, double _double) 7202c393a42Smrg{ 721a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 7222c393a42Smrg if (!vstack) 7232c393a42Smrg return FcFalse; 7242c393a42Smrg vstack->u._double = _double; 7252c393a42Smrg vstack->tag = FcVStackDouble; 7262c393a42Smrg return FcTrue; 7272c393a42Smrg} 7282c393a42Smrg 7292c393a42Smrgstatic FcBool 7302c393a42SmrgFcVStackPushMatrix (FcConfigParse *parse, FcMatrix *matrix) 7312c393a42Smrg{ 732a6844aabSmrg FcVStack *vstack; 7332c393a42Smrg matrix = FcMatrixCopy (matrix); 7342c393a42Smrg if (!matrix) 7352c393a42Smrg return FcFalse; 736a6844aabSmrg vstack = FcVStackCreateAndPush (parse); 737a6844aabSmrg if (!vstack) 738a6844aabSmrg return FcFalse; 7392c393a42Smrg vstack->u.matrix = matrix; 7402c393a42Smrg vstack->tag = FcVStackMatrix; 7412c393a42Smrg return FcTrue; 7422c393a42Smrg} 7432c393a42Smrg 7442c393a42Smrgstatic FcBool 745a6844aabSmrgFcVStackPushBool (FcConfigParse *parse, FcBool bool_) 7462c393a42Smrg{ 747a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 7482c393a42Smrg if (!vstack) 7492c393a42Smrg return FcFalse; 750a6844aabSmrg vstack->u.bool_ = bool_; 7512c393a42Smrg vstack->tag = FcVStackBool; 7522c393a42Smrg return FcTrue; 7532c393a42Smrg} 7542c393a42Smrg 7552c393a42Smrgstatic FcBool 7562c393a42SmrgFcVStackPushTest (FcConfigParse *parse, FcTest *test) 7572c393a42Smrg{ 758a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 7592c393a42Smrg if (!vstack) 7602c393a42Smrg return FcFalse; 7612c393a42Smrg vstack->u.test = test; 7622c393a42Smrg vstack->tag = FcVStackTest; 7632c393a42Smrg return FcTrue; 7642c393a42Smrg} 7652c393a42Smrg 7662c393a42Smrgstatic FcBool 7672c393a42SmrgFcVStackPushExpr (FcConfigParse *parse, FcVStackTag tag, FcExpr *expr) 7682c393a42Smrg{ 769a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 7702c393a42Smrg if (!vstack) 7712c393a42Smrg return FcFalse; 7722c393a42Smrg vstack->u.expr = expr; 7732c393a42Smrg vstack->tag = tag; 7742c393a42Smrg return FcTrue; 7752c393a42Smrg} 7762c393a42Smrg 7772c393a42Smrgstatic FcBool 7782c393a42SmrgFcVStackPushEdit (FcConfigParse *parse, FcEdit *edit) 7792c393a42Smrg{ 780a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 7812c393a42Smrg if (!vstack) 7822c393a42Smrg return FcFalse; 7832c393a42Smrg vstack->u.edit = edit; 7842c393a42Smrg vstack->tag = FcVStackEdit; 7852c393a42Smrg return FcTrue; 7862c393a42Smrg} 7872c393a42Smrg 7882c393a42Smrgstatic FcBool 7892c393a42SmrgFcVStackPushPattern (FcConfigParse *parse, FcPattern *pattern) 7902c393a42Smrg{ 791a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 7922c393a42Smrg if (!vstack) 7932c393a42Smrg return FcFalse; 7942c393a42Smrg vstack->u.pattern = pattern; 7952c393a42Smrg vstack->tag = FcVStackPattern; 7962c393a42Smrg return FcTrue; 7972c393a42Smrg} 7982c393a42Smrg 7992c393a42Smrgstatic FcVStack * 8002c393a42SmrgFcVStackFetch (FcConfigParse *parse, int off) 8012c393a42Smrg{ 8022c393a42Smrg FcVStack *vstack; 8032c393a42Smrg 8042c393a42Smrg for (vstack = parse->vstack; vstack && off-- > 0; vstack = vstack->prev); 8052c393a42Smrg return vstack; 8062c393a42Smrg} 8072c393a42Smrg 808a6844aabSmrgstatic FcVStack * 809a6844aabSmrgFcVStackPeek (FcConfigParse *parse) 8102c393a42Smrg{ 811a6844aabSmrg FcVStack *vstack = parse->vstack; 812a6844aabSmrg 813a6844aabSmrg return vstack && vstack->pstack == parse->pstack ? vstack : 0; 8142c393a42Smrg} 8152c393a42Smrg 816a6844aabSmrgstatic void 817a6844aabSmrgFcVStackPopAndDestroy (FcConfigParse *parse) 8182c393a42Smrg{ 8192c393a42Smrg FcVStack *vstack = parse->vstack; 8202c393a42Smrg 8212c393a42Smrg if (!vstack || vstack->pstack != parse->pstack) 822a6844aabSmrg return; 823a6844aabSmrg 8242c393a42Smrg parse->vstack = vstack->prev; 825a6844aabSmrg 826a6844aabSmrg switch (vstack->tag) { 827a6844aabSmrg case FcVStackNone: 828a6844aabSmrg break; 829a6844aabSmrg case FcVStackFamily: 830a6844aabSmrg break; 831a6844aabSmrg case FcVStackString: 832a6844aabSmrg case FcVStackField: 833a6844aabSmrg case FcVStackConstant: 834a6844aabSmrg case FcVStackGlob: 835a6844aabSmrg FcStrFree (vstack->u.string); 836a6844aabSmrg break; 837a6844aabSmrg case FcVStackPattern: 838a6844aabSmrg FcPatternDestroy (vstack->u.pattern); 839a6844aabSmrg break; 840a6844aabSmrg case FcVStackInteger: 841a6844aabSmrg case FcVStackDouble: 842a6844aabSmrg break; 843a6844aabSmrg case FcVStackMatrix: 844a6844aabSmrg FcMatrixFree (vstack->u.matrix); 845a6844aabSmrg break; 846a6844aabSmrg case FcVStackBool: 847a6844aabSmrg break; 848a6844aabSmrg case FcVStackTest: 849a6844aabSmrg FcTestDestroy (vstack->u.test); 850a6844aabSmrg break; 851a6844aabSmrg case FcVStackExpr: 852a6844aabSmrg case FcVStackPrefer: 853a6844aabSmrg case FcVStackAccept: 854a6844aabSmrg case FcVStackDefault: 855a6844aabSmrg FcExprDestroy (vstack->u.expr); 856a6844aabSmrg break; 857a6844aabSmrg case FcVStackEdit: 858a6844aabSmrg FcEditDestroy (vstack->u.edit); 859a6844aabSmrg break; 860a6844aabSmrg } 861a6844aabSmrg 862a6844aabSmrg if (vstack == &parse->vstack_static[parse->vstack_static_used - 1]) 863a6844aabSmrg parse->vstack_static_used--; 864a6844aabSmrg else 865a6844aabSmrg { 866a6844aabSmrg FcMemFree (FC_MEM_VSTACK, sizeof (FcVStack)); 867a6844aabSmrg free (vstack); 868a6844aabSmrg } 869a6844aabSmrg} 870a6844aabSmrg 871a6844aabSmrgstatic void 872a6844aabSmrgFcVStackClear (FcConfigParse *parse) 873a6844aabSmrg{ 874a6844aabSmrg while (FcVStackPeek (parse)) 875a6844aabSmrg FcVStackPopAndDestroy (parse); 8762c393a42Smrg} 8772c393a42Smrg 8782c393a42Smrgstatic int 8792c393a42SmrgFcVStackElements (FcConfigParse *parse) 8802c393a42Smrg{ 8812c393a42Smrg int h = 0; 8822c393a42Smrg FcVStack *vstack = parse->vstack; 8832c393a42Smrg while (vstack && vstack->pstack == parse->pstack) 8842c393a42Smrg { 8852c393a42Smrg h++; 8862c393a42Smrg vstack = vstack->prev; 8872c393a42Smrg } 8882c393a42Smrg return h; 8892c393a42Smrg} 8902c393a42Smrg 8912c393a42Smrgstatic FcChar8 ** 892a6844aabSmrgFcConfigSaveAttr (const XML_Char **attr, FcChar8 **buf, int size_bytes) 8932c393a42Smrg{ 8942c393a42Smrg int slen; 8952c393a42Smrg int i; 8962c393a42Smrg FcChar8 **new; 8972c393a42Smrg FcChar8 *s; 8982c393a42Smrg 8992c393a42Smrg if (!attr) 9002c393a42Smrg return 0; 9012c393a42Smrg slen = 0; 9022c393a42Smrg for (i = 0; attr[i]; i++) 9032c393a42Smrg slen += strlen ((char *) attr[i]) + 1; 904a6844aabSmrg if (i == 0) 9052c393a42Smrg return 0; 906a6844aabSmrg slen += (i + 1) * sizeof (FcChar8 *); 907a6844aabSmrg if (slen <= size_bytes) 908a6844aabSmrg new = buf; 909a6844aabSmrg else 910a6844aabSmrg { 911a6844aabSmrg new = malloc (slen); 912a6844aabSmrg if (!new) 913a6844aabSmrg { 914a6844aabSmrg FcConfigMessage (0, FcSevereError, "out of memory"); 915a6844aabSmrg return 0; 916a6844aabSmrg } 917a6844aabSmrg FcMemAlloc (FC_MEM_ATTR, 1); /* size is too expensive */ 918a6844aabSmrg } 9192c393a42Smrg s = (FcChar8 *) (new + (i + 1)); 9202c393a42Smrg for (i = 0; attr[i]; i++) 9212c393a42Smrg { 9222c393a42Smrg new[i] = s; 9232c393a42Smrg strcpy ((char *) s, (char *) attr[i]); 9242c393a42Smrg s += strlen ((char *) s) + 1; 9252c393a42Smrg } 9262c393a42Smrg new[i] = 0; 9272c393a42Smrg return new; 9282c393a42Smrg} 9292c393a42Smrg 9302c393a42Smrgstatic FcBool 9312c393a42SmrgFcPStackPush (FcConfigParse *parse, FcElement element, const XML_Char **attr) 9322c393a42Smrg{ 933a6844aabSmrg FcPStack *new; 9342c393a42Smrg 935a6844aabSmrg if (parse->pstack_static_used < sizeof (parse->pstack_static) / sizeof (parse->pstack_static[0])) 936a6844aabSmrg new = &parse->pstack_static[parse->pstack_static_used++]; 937a6844aabSmrg else 9382c393a42Smrg { 939a6844aabSmrg new = malloc (sizeof (FcPStack)); 940a6844aabSmrg if (!new) 9412c393a42Smrg return FcFalse; 942a6844aabSmrg FcMemAlloc (FC_MEM_PSTACK, sizeof (FcPStack)); 9432c393a42Smrg } 944a6844aabSmrg 945a6844aabSmrg new->prev = parse->pstack; 946a6844aabSmrg new->element = element; 947a6844aabSmrg new->attr = FcConfigSaveAttr (attr, new->attr_buf_static, sizeof (new->attr_buf_static)); 9482c393a42Smrg FcStrBufInit (&new->str, 0, 0); 9492c393a42Smrg parse->pstack = new; 9502c393a42Smrg return FcTrue; 9512c393a42Smrg} 9522c393a42Smrg 9532c393a42Smrgstatic FcBool 9542c393a42SmrgFcPStackPop (FcConfigParse *parse) 9552c393a42Smrg{ 9562c393a42Smrg FcPStack *old; 9572c393a42Smrg 9582c393a42Smrg if (!parse->pstack) 9592c393a42Smrg { 9602c393a42Smrg FcConfigMessage (parse, FcSevereError, "mismatching element"); 9612c393a42Smrg return FcFalse; 9622c393a42Smrg } 9632c393a42Smrg FcVStackClear (parse); 9642c393a42Smrg old = parse->pstack; 9652c393a42Smrg parse->pstack = old->prev; 9662c393a42Smrg FcStrBufDestroy (&old->str); 967a6844aabSmrg if (old->attr && old->attr != old->attr_buf_static) 9682c393a42Smrg { 9692c393a42Smrg FcMemFree (FC_MEM_ATTR, 1); /* size is to expensive */ 9702c393a42Smrg free (old->attr); 9712c393a42Smrg } 972a6844aabSmrg 973a6844aabSmrg if (old == &parse->pstack_static[parse->pstack_static_used - 1]) 974a6844aabSmrg parse->pstack_static_used--; 975a6844aabSmrg else 976a6844aabSmrg { 977a6844aabSmrg FcMemFree (FC_MEM_PSTACK, sizeof (FcPStack)); 978a6844aabSmrg free (old); 979a6844aabSmrg } 9802c393a42Smrg return FcTrue; 9812c393a42Smrg} 9822c393a42Smrg 9832c393a42Smrgstatic FcBool 9842c393a42SmrgFcConfigInit (FcConfigParse *parse, const FcChar8 *name, FcConfig *config, XML_Parser parser) 9852c393a42Smrg{ 9862c393a42Smrg parse->pstack = 0; 987a6844aabSmrg parse->pstack_static_used = 0; 9882c393a42Smrg parse->vstack = 0; 989a6844aabSmrg parse->vstack_static_used = 0; 9902c393a42Smrg parse->error = FcFalse; 9912c393a42Smrg parse->name = name; 9922c393a42Smrg parse->config = config; 9932c393a42Smrg parse->parser = parser; 9942c393a42Smrg return FcTrue; 9952c393a42Smrg} 9962c393a42Smrg 9972c393a42Smrgstatic void 9982c393a42SmrgFcConfigCleanup (FcConfigParse *parse) 9992c393a42Smrg{ 10002c393a42Smrg while (parse->pstack) 10012c393a42Smrg FcPStackPop (parse); 10022c393a42Smrg} 10032c393a42Smrg 10042c393a42Smrgstatic const FcChar8 * 10052c393a42SmrgFcConfigGetAttribute (FcConfigParse *parse, const char *attr) 10062c393a42Smrg{ 10072c393a42Smrg FcChar8 **attrs; 10082c393a42Smrg if (!parse->pstack) 10092c393a42Smrg return 0; 10102c393a42Smrg 10112c393a42Smrg attrs = parse->pstack->attr; 10122c393a42Smrg if (!attrs) 10132c393a42Smrg return 0; 10142c393a42Smrg 10152c393a42Smrg while (*attrs) 10162c393a42Smrg { 10172c393a42Smrg if (!strcmp ((char *) *attrs, attr)) 10182c393a42Smrg return attrs[1]; 10192c393a42Smrg attrs += 2; 10202c393a42Smrg } 10212c393a42Smrg return 0; 10222c393a42Smrg} 10232c393a42Smrg 10242c393a42Smrgstatic void 10252c393a42SmrgFcStartElement(void *userData, const XML_Char *name, const XML_Char **attr) 10262c393a42Smrg{ 10272c393a42Smrg FcConfigParse *parse = userData; 10282c393a42Smrg FcElement element; 10292c393a42Smrg 10302c393a42Smrg element = FcElementMap (name); 10312c393a42Smrg if (element == FcElementUnknown) 10322c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "unknown element \"%s\"", name); 10332c393a42Smrg 10342c393a42Smrg if (!FcPStackPush (parse, element, attr)) 10352c393a42Smrg { 10362c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 10372c393a42Smrg return; 10382c393a42Smrg } 10392c393a42Smrg return; 10402c393a42Smrg} 10412c393a42Smrg 10422c393a42Smrgstatic void 10432c393a42SmrgFcParseBlank (FcConfigParse *parse) 10442c393a42Smrg{ 10452c393a42Smrg int n = FcVStackElements (parse); 10462c393a42Smrg while (n-- > 0) 10472c393a42Smrg { 10482c393a42Smrg FcVStack *v = FcVStackFetch (parse, n); 10492c393a42Smrg if (v->tag != FcVStackInteger) 10502c393a42Smrg FcConfigMessage (parse, FcSevereError, "non-integer blank"); 10512c393a42Smrg else 10522c393a42Smrg { 10532c393a42Smrg if (!parse->config->blanks) 10542c393a42Smrg { 10552c393a42Smrg parse->config->blanks = FcBlanksCreate (); 10562c393a42Smrg if (!parse->config->blanks) 10572c393a42Smrg { 10582c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 10592c393a42Smrg break; 10602c393a42Smrg } 10612c393a42Smrg } 10622c393a42Smrg if (!FcBlanksAdd (parse->config->blanks, v->u.integer)) 10632c393a42Smrg { 10642c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 10652c393a42Smrg break; 10662c393a42Smrg } 10672c393a42Smrg } 10682c393a42Smrg } 10692c393a42Smrg} 10702c393a42Smrg 10712c393a42Smrgstatic void 10722c393a42SmrgFcParseRescan (FcConfigParse *parse) 10732c393a42Smrg{ 10742c393a42Smrg int n = FcVStackElements (parse); 10752c393a42Smrg while (n-- > 0) 10762c393a42Smrg { 10772c393a42Smrg FcVStack *v = FcVStackFetch (parse, n); 10782c393a42Smrg if (v->tag != FcVStackInteger) 10792c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "non-integer rescan"); 10802c393a42Smrg else 10812c393a42Smrg parse->config->rescanInterval = v->u.integer; 10822c393a42Smrg } 10832c393a42Smrg} 10842c393a42Smrg 10852c393a42Smrgstatic void 10862c393a42SmrgFcParseInt (FcConfigParse *parse) 10872c393a42Smrg{ 10882c393a42Smrg FcChar8 *s, *end; 10892c393a42Smrg int l; 10902c393a42Smrg 10912c393a42Smrg if (!parse->pstack) 10922c393a42Smrg return; 1093a6844aabSmrg s = FcStrBufDoneStatic (&parse->pstack->str); 10942c393a42Smrg if (!s) 10952c393a42Smrg { 10962c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 10972c393a42Smrg return; 10982c393a42Smrg } 10992c393a42Smrg end = 0; 11002c393a42Smrg l = (int) strtol ((char *) s, (char **)&end, 0); 11012c393a42Smrg if (end != s + strlen ((char *) s)) 11022c393a42Smrg FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid integer", s); 11032c393a42Smrg else 11042c393a42Smrg FcVStackPushInteger (parse, l); 1105a6844aabSmrg FcStrBufDestroy (&parse->pstack->str); 11062c393a42Smrg} 11072c393a42Smrg 11082c393a42Smrg/* 11092c393a42Smrg * idea copied from glib g_ascii_strtod with 11102c393a42Smrg * permission of the author (Alexander Larsson) 11112c393a42Smrg */ 11122c393a42Smrg 11132c393a42Smrg#include <locale.h> 11142c393a42Smrg 11152c393a42Smrgstatic double 11162c393a42SmrgFcStrtod (char *s, char **end) 11172c393a42Smrg{ 11182c393a42Smrg struct lconv *locale_data; 11192c393a42Smrg char *dot; 11202c393a42Smrg double v; 11212c393a42Smrg 11222c393a42Smrg /* 11232c393a42Smrg * Have to swap the decimal point to match the current locale 11242c393a42Smrg * if that locale doesn't use 0x2e 11252c393a42Smrg */ 11262c393a42Smrg if ((dot = strchr (s, 0x2e)) && 11272c393a42Smrg (locale_data = localeconv ()) && 11282c393a42Smrg (locale_data->decimal_point[0] != 0x2e || 11292c393a42Smrg locale_data->decimal_point[1] != 0)) 11302c393a42Smrg { 11312c393a42Smrg char buf[128]; 11322c393a42Smrg int slen = strlen (s); 11332c393a42Smrg int dlen = strlen (locale_data->decimal_point); 11342c393a42Smrg 11352c393a42Smrg if (slen + dlen > (int) sizeof (buf)) 11362c393a42Smrg { 11372c393a42Smrg if (end) 11382c393a42Smrg *end = s; 11392c393a42Smrg v = 0; 11402c393a42Smrg } 11412c393a42Smrg else 11422c393a42Smrg { 11432c393a42Smrg char *buf_end; 11442c393a42Smrg /* mantissa */ 11452c393a42Smrg strncpy (buf, s, dot - s); 11462c393a42Smrg /* decimal point */ 11472c393a42Smrg strcpy (buf + (dot - s), locale_data->decimal_point); 11482c393a42Smrg /* rest of number */ 11492c393a42Smrg strcpy (buf + (dot - s) + dlen, dot + 1); 11502c393a42Smrg buf_end = 0; 11512c393a42Smrg v = strtod (buf, &buf_end); 11522c393a42Smrg if (buf_end) { 11532c393a42Smrg buf_end = s + (buf_end - buf); 11542c393a42Smrg if (buf_end > dot) 11552c393a42Smrg buf_end -= dlen - 1; 11562c393a42Smrg } 11572c393a42Smrg if (end) 11582c393a42Smrg *end = buf_end; 11592c393a42Smrg } 11602c393a42Smrg } 11612c393a42Smrg else 11622c393a42Smrg v = strtod (s, end); 11632c393a42Smrg return v; 11642c393a42Smrg} 11652c393a42Smrg 11662c393a42Smrgstatic void 11672c393a42SmrgFcParseDouble (FcConfigParse *parse) 11682c393a42Smrg{ 11692c393a42Smrg FcChar8 *s, *end; 11702c393a42Smrg double d; 11712c393a42Smrg 11722c393a42Smrg if (!parse->pstack) 11732c393a42Smrg return; 1174a6844aabSmrg s = FcStrBufDoneStatic (&parse->pstack->str); 11752c393a42Smrg if (!s) 11762c393a42Smrg { 11772c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 11782c393a42Smrg return; 11792c393a42Smrg } 11802c393a42Smrg end = 0; 11812c393a42Smrg d = FcStrtod ((char *) s, (char **)&end); 11822c393a42Smrg if (end != s + strlen ((char *) s)) 11832c393a42Smrg FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid double", s); 11842c393a42Smrg else 11852c393a42Smrg FcVStackPushDouble (parse, d); 1186a6844aabSmrg FcStrBufDestroy (&parse->pstack->str); 11872c393a42Smrg} 11882c393a42Smrg 11892c393a42Smrgstatic void 11902c393a42SmrgFcParseString (FcConfigParse *parse, FcVStackTag tag) 11912c393a42Smrg{ 11922c393a42Smrg FcChar8 *s; 11932c393a42Smrg 11942c393a42Smrg if (!parse->pstack) 11952c393a42Smrg return; 11962c393a42Smrg s = FcStrBufDone (&parse->pstack->str); 11972c393a42Smrg if (!s) 11982c393a42Smrg { 11992c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 12002c393a42Smrg return; 12012c393a42Smrg } 12022c393a42Smrg if (!FcVStackPushString (parse, tag, s)) 12032c393a42Smrg FcStrFree (s); 12042c393a42Smrg} 12052c393a42Smrg 12062c393a42Smrgstatic void 12072c393a42SmrgFcParseMatrix (FcConfigParse *parse) 12082c393a42Smrg{ 12092c393a42Smrg FcVStack *vstack; 12102c393a42Smrg enum { m_done, m_xx, m_xy, m_yx, m_yy } matrix_state = m_yy; 12112c393a42Smrg FcMatrix m; 12122c393a42Smrg 1213a6844aabSmrg while ((vstack = FcVStackPeek (parse))) 12142c393a42Smrg { 12152c393a42Smrg double v; 12162c393a42Smrg switch (vstack->tag) { 12172c393a42Smrg case FcVStackInteger: 12182c393a42Smrg v = vstack->u.integer; 12192c393a42Smrg break; 12202c393a42Smrg case FcVStackDouble: 12212c393a42Smrg v = vstack->u._double; 12222c393a42Smrg break; 12232c393a42Smrg default: 12242c393a42Smrg FcConfigMessage (parse, FcSevereError, "non-double matrix element"); 12252c393a42Smrg v = 1.0; 12262c393a42Smrg break; 12272c393a42Smrg } 12282c393a42Smrg switch (matrix_state) { 12292c393a42Smrg case m_xx: m.xx = v; break; 12302c393a42Smrg case m_xy: m.xy = v; break; 12312c393a42Smrg case m_yx: m.yx = v; break; 12322c393a42Smrg case m_yy: m.yy = v; break; 12332c393a42Smrg default: break; 12342c393a42Smrg } 1235a6844aabSmrg FcVStackPopAndDestroy (parse); 12362c393a42Smrg matrix_state--; 12372c393a42Smrg } 12382c393a42Smrg if (matrix_state != m_done) 12392c393a42Smrg FcConfigMessage (parse, FcSevereError, "wrong number of matrix elements"); 12402c393a42Smrg else 12412c393a42Smrg FcVStackPushMatrix (parse, &m); 12422c393a42Smrg} 12432c393a42Smrg 12442c393a42Smrgstatic FcBool 1245a6844aabSmrgFcConfigLexBool (FcConfigParse *parse, const FcChar8 *bool_) 12462c393a42Smrg{ 12472c393a42Smrg FcBool result = FcFalse; 12482c393a42Smrg 1249a6844aabSmrg if (!FcNameBool (bool_, &result)) 12502c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "\"%s\" is not known boolean", 1251a6844aabSmrg bool_); 12522c393a42Smrg return result; 12532c393a42Smrg} 12542c393a42Smrg 12552c393a42Smrgstatic void 12562c393a42SmrgFcParseBool (FcConfigParse *parse) 12572c393a42Smrg{ 12582c393a42Smrg FcChar8 *s; 12592c393a42Smrg 12602c393a42Smrg if (!parse->pstack) 12612c393a42Smrg return; 1262a6844aabSmrg s = FcStrBufDoneStatic (&parse->pstack->str); 12632c393a42Smrg if (!s) 12642c393a42Smrg { 12652c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 12662c393a42Smrg return; 12672c393a42Smrg } 12682c393a42Smrg FcVStackPushBool (parse, FcConfigLexBool (parse, s)); 1269a6844aabSmrg FcStrBufDestroy (&parse->pstack->str); 12702c393a42Smrg} 12712c393a42Smrg 12722c393a42Smrgstatic FcBool 12732c393a42SmrgFcConfigLexBinding (FcConfigParse *parse, 12742c393a42Smrg const FcChar8 *binding_string, 12752c393a42Smrg FcValueBinding *binding_ret) 12762c393a42Smrg{ 12772c393a42Smrg FcValueBinding binding; 12782c393a42Smrg 12792c393a42Smrg if (!binding_string) 12802c393a42Smrg binding = FcValueBindingWeak; 12812c393a42Smrg else 12822c393a42Smrg { 12832c393a42Smrg if (!strcmp ((char *) binding_string, "weak")) 12842c393a42Smrg binding = FcValueBindingWeak; 12852c393a42Smrg else if (!strcmp ((char *) binding_string, "strong")) 12862c393a42Smrg binding = FcValueBindingStrong; 12872c393a42Smrg else if (!strcmp ((char *) binding_string, "same")) 12882c393a42Smrg binding = FcValueBindingSame; 12892c393a42Smrg else 12902c393a42Smrg { 12912c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "invalid binding \"%s\"", binding_string); 12922c393a42Smrg return FcFalse; 12932c393a42Smrg } 12942c393a42Smrg } 12952c393a42Smrg *binding_ret = binding; 12962c393a42Smrg return FcTrue; 12972c393a42Smrg} 12982c393a42Smrg 12992c393a42Smrgstatic void 13002c393a42SmrgFcParseFamilies (FcConfigParse *parse, FcVStackTag tag) 13012c393a42Smrg{ 13022c393a42Smrg FcVStack *vstack; 13032c393a42Smrg FcExpr *left, *expr = 0, *new; 13042c393a42Smrg 1305a6844aabSmrg while ((vstack = FcVStackPeek (parse))) 13062c393a42Smrg { 13072c393a42Smrg if (vstack->tag != FcVStackFamily) 13082c393a42Smrg { 13092c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "non-family"); 1310a6844aabSmrg FcVStackPopAndDestroy (parse); 13112c393a42Smrg continue; 13122c393a42Smrg } 13132c393a42Smrg left = vstack->u.expr; 13142c393a42Smrg vstack->tag = FcVStackNone; 1315a6844aabSmrg FcVStackPopAndDestroy (parse); 13162c393a42Smrg if (expr) 13172c393a42Smrg { 1318a6844aabSmrg new = FcExprCreateOp (parse->config, left, FcOpComma, expr); 13192c393a42Smrg if (!new) 13202c393a42Smrg { 13212c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 13222c393a42Smrg FcExprDestroy (left); 13232c393a42Smrg FcExprDestroy (expr); 13242c393a42Smrg break; 13252c393a42Smrg } 13262c393a42Smrg expr = new; 13272c393a42Smrg } 13282c393a42Smrg else 13292c393a42Smrg expr = left; 13302c393a42Smrg } 13312c393a42Smrg if (expr) 13322c393a42Smrg { 13332c393a42Smrg if (!FcVStackPushExpr (parse, tag, expr)) 13342c393a42Smrg { 13352c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 13362c393a42Smrg FcExprDestroy (expr); 13372c393a42Smrg } 13382c393a42Smrg } 13392c393a42Smrg} 13402c393a42Smrg 13412c393a42Smrgstatic void 13422c393a42SmrgFcParseFamily (FcConfigParse *parse) 13432c393a42Smrg{ 13442c393a42Smrg FcChar8 *s; 13452c393a42Smrg FcExpr *expr; 13462c393a42Smrg 13472c393a42Smrg if (!parse->pstack) 13482c393a42Smrg return; 1349a6844aabSmrg s = FcStrBufDoneStatic (&parse->pstack->str); 13502c393a42Smrg if (!s) 13512c393a42Smrg { 13522c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 13532c393a42Smrg return; 13542c393a42Smrg } 1355a6844aabSmrg expr = FcExprCreateString (parse->config, s); 1356a6844aabSmrg FcStrBufDestroy (&parse->pstack->str); 13572c393a42Smrg if (expr) 13582c393a42Smrg FcVStackPushExpr (parse, FcVStackFamily, expr); 13592c393a42Smrg} 13602c393a42Smrg 13612c393a42Smrgstatic void 13622c393a42SmrgFcParseAlias (FcConfigParse *parse) 13632c393a42Smrg{ 13642c393a42Smrg FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0; 13652c393a42Smrg FcEdit *edit = 0, *next; 13662c393a42Smrg FcVStack *vstack; 13672c393a42Smrg FcTest *test; 13682c393a42Smrg FcValueBinding binding; 13692c393a42Smrg 13702c393a42Smrg if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding)) 13712c393a42Smrg return; 1372a6844aabSmrg while ((vstack = FcVStackPeek (parse))) 13732c393a42Smrg { 13742c393a42Smrg switch (vstack->tag) { 13752c393a42Smrg case FcVStackFamily: 13762c393a42Smrg if (family) 13772c393a42Smrg { 1378a6844aabSmrg new = FcExprCreateOp (parse->config, vstack->u.expr, FcOpComma, family); 13792c393a42Smrg if (!new) 13802c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 13812c393a42Smrg else 13822c393a42Smrg family = new; 13832c393a42Smrg } 13842c393a42Smrg else 13852c393a42Smrg new = vstack->u.expr; 13862c393a42Smrg if (new) 13872c393a42Smrg { 13882c393a42Smrg family = new; 13892c393a42Smrg vstack->tag = FcVStackNone; 13902c393a42Smrg } 13912c393a42Smrg break; 13922c393a42Smrg case FcVStackPrefer: 13932c393a42Smrg if (prefer) 13942c393a42Smrg FcExprDestroy (prefer); 13952c393a42Smrg prefer = vstack->u.expr; 13962c393a42Smrg vstack->tag = FcVStackNone; 13972c393a42Smrg break; 13982c393a42Smrg case FcVStackAccept: 13992c393a42Smrg if (accept) 14002c393a42Smrg FcExprDestroy (accept); 14012c393a42Smrg accept = vstack->u.expr; 14022c393a42Smrg vstack->tag = FcVStackNone; 14032c393a42Smrg break; 14042c393a42Smrg case FcVStackDefault: 14052c393a42Smrg if (def) 14062c393a42Smrg FcExprDestroy (def); 14072c393a42Smrg def = vstack->u.expr; 14082c393a42Smrg vstack->tag = FcVStackNone; 14092c393a42Smrg break; 14102c393a42Smrg default: 14112c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "bad alias"); 14122c393a42Smrg break; 14132c393a42Smrg } 1414a6844aabSmrg FcVStackPopAndDestroy (parse); 14152c393a42Smrg } 14162c393a42Smrg if (!family) 14172c393a42Smrg { 14182c393a42Smrg FcConfigMessage (parse, FcSevereError, "missing family in alias"); 14192c393a42Smrg if (prefer) 14202c393a42Smrg FcExprDestroy (prefer); 14212c393a42Smrg if (accept) 14222c393a42Smrg FcExprDestroy (accept); 14232c393a42Smrg if (def) 14242c393a42Smrg FcExprDestroy (def); 14252c393a42Smrg return; 14262c393a42Smrg } 14272c393a42Smrg if (prefer) 14282c393a42Smrg { 14292c393a42Smrg edit = FcEditCreate (parse, 14302c393a42Smrg FC_FAMILY_OBJECT, 14312c393a42Smrg FcOpPrepend, 14322c393a42Smrg prefer, 14332c393a42Smrg binding); 14342c393a42Smrg if (edit) 14352c393a42Smrg edit->next = 0; 14362c393a42Smrg else 14372c393a42Smrg FcExprDestroy (prefer); 14382c393a42Smrg } 14392c393a42Smrg if (accept) 14402c393a42Smrg { 14412c393a42Smrg next = edit; 14422c393a42Smrg edit = FcEditCreate (parse, 14432c393a42Smrg FC_FAMILY_OBJECT, 14442c393a42Smrg FcOpAppend, 14452c393a42Smrg accept, 14462c393a42Smrg binding); 14472c393a42Smrg if (edit) 14482c393a42Smrg edit->next = next; 14492c393a42Smrg else 14502c393a42Smrg FcExprDestroy (accept); 14512c393a42Smrg } 14522c393a42Smrg if (def) 14532c393a42Smrg { 14542c393a42Smrg next = edit; 14552c393a42Smrg edit = FcEditCreate (parse, 14562c393a42Smrg FC_FAMILY_OBJECT, 14572c393a42Smrg FcOpAppendLast, 14582c393a42Smrg def, 14592c393a42Smrg binding); 14602c393a42Smrg if (edit) 14612c393a42Smrg edit->next = next; 14622c393a42Smrg else 14632c393a42Smrg FcExprDestroy (def); 14642c393a42Smrg } 14652c393a42Smrg if (edit) 14662c393a42Smrg { 14672c393a42Smrg test = FcTestCreate (parse, FcMatchPattern, 14682c393a42Smrg FcQualAny, 14692c393a42Smrg (FcChar8 *) FC_FAMILY, 14702c393a42Smrg FcOpEqual, 14712c393a42Smrg family); 14722c393a42Smrg if (test) 14732c393a42Smrg if (!FcConfigAddEdit (parse->config, test, edit, FcMatchPattern)) 14742c393a42Smrg FcTestDestroy (test); 14752c393a42Smrg } 14762c393a42Smrg else 14772c393a42Smrg FcExprDestroy (family); 14782c393a42Smrg} 14792c393a42Smrg 14802c393a42Smrgstatic FcExpr * 14812c393a42SmrgFcPopExpr (FcConfigParse *parse) 14822c393a42Smrg{ 1483a6844aabSmrg FcVStack *vstack = FcVStackPeek (parse); 14842c393a42Smrg FcExpr *expr = 0; 14852c393a42Smrg if (!vstack) 14862c393a42Smrg return 0; 14872c393a42Smrg switch (vstack->tag) { 14882c393a42Smrg case FcVStackNone: 14892c393a42Smrg break; 14902c393a42Smrg case FcVStackString: 14912c393a42Smrg case FcVStackFamily: 1492a6844aabSmrg expr = FcExprCreateString (parse->config, vstack->u.string); 14932c393a42Smrg break; 14942c393a42Smrg case FcVStackField: 1495a6844aabSmrg expr = FcExprCreateField (parse->config, (char *) vstack->u.string); 14962c393a42Smrg break; 14972c393a42Smrg case FcVStackConstant: 1498a6844aabSmrg expr = FcExprCreateConst (parse->config, vstack->u.string); 14992c393a42Smrg break; 15002c393a42Smrg case FcVStackGlob: 15012c393a42Smrg /* XXX: What's the correct action here? (CDW) */ 15022c393a42Smrg break; 15032c393a42Smrg case FcVStackPrefer: 15042c393a42Smrg case FcVStackAccept: 15052c393a42Smrg case FcVStackDefault: 15062c393a42Smrg expr = vstack->u.expr; 15072c393a42Smrg vstack->tag = FcVStackNone; 15082c393a42Smrg break; 15092c393a42Smrg case FcVStackInteger: 1510a6844aabSmrg expr = FcExprCreateInteger (parse->config, vstack->u.integer); 15112c393a42Smrg break; 15122c393a42Smrg case FcVStackDouble: 1513a6844aabSmrg expr = FcExprCreateDouble (parse->config, vstack->u._double); 15142c393a42Smrg break; 15152c393a42Smrg case FcVStackMatrix: 1516a6844aabSmrg expr = FcExprCreateMatrix (parse->config, vstack->u.matrix); 15172c393a42Smrg break; 15182c393a42Smrg case FcVStackBool: 1519a6844aabSmrg expr = FcExprCreateBool (parse->config, vstack->u.bool_); 15202c393a42Smrg break; 15212c393a42Smrg case FcVStackTest: 15222c393a42Smrg break; 15232c393a42Smrg case FcVStackExpr: 15242c393a42Smrg expr = vstack->u.expr; 15252c393a42Smrg vstack->tag = FcVStackNone; 15262c393a42Smrg break; 15272c393a42Smrg case FcVStackEdit: 15282c393a42Smrg break; 15292c393a42Smrg default: 15302c393a42Smrg break; 15312c393a42Smrg } 1532a6844aabSmrg FcVStackPopAndDestroy (parse); 15332c393a42Smrg return expr; 15342c393a42Smrg} 15352c393a42Smrg 15362c393a42Smrg/* 15372c393a42Smrg * This builds a tree of binary operations. Note 15382c393a42Smrg * that every operator is defined so that if only 15392c393a42Smrg * a single operand is contained, the value of the 15402c393a42Smrg * whole expression is the value of the operand. 15412c393a42Smrg * 15422c393a42Smrg * This code reduces in that case to returning that 15432c393a42Smrg * operand. 15442c393a42Smrg */ 15452c393a42Smrgstatic FcExpr * 15462c393a42SmrgFcPopBinary (FcConfigParse *parse, FcOp op) 15472c393a42Smrg{ 15482c393a42Smrg FcExpr *left, *expr = 0, *new; 15492c393a42Smrg 15502c393a42Smrg while ((left = FcPopExpr (parse))) 15512c393a42Smrg { 15522c393a42Smrg if (expr) 15532c393a42Smrg { 1554a6844aabSmrg new = FcExprCreateOp (parse->config, left, op, expr); 15552c393a42Smrg if (!new) 15562c393a42Smrg { 15572c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 15582c393a42Smrg FcExprDestroy (left); 15592c393a42Smrg FcExprDestroy (expr); 15602c393a42Smrg return 0; 15612c393a42Smrg } 15622c393a42Smrg expr = new; 15632c393a42Smrg } 15642c393a42Smrg else 15652c393a42Smrg expr = left; 15662c393a42Smrg } 15672c393a42Smrg return expr; 15682c393a42Smrg} 15692c393a42Smrg 15702c393a42Smrgstatic void 15712c393a42SmrgFcParseBinary (FcConfigParse *parse, FcOp op) 15722c393a42Smrg{ 15732c393a42Smrg FcExpr *expr = FcPopBinary (parse, op); 15742c393a42Smrg if (expr) 15752c393a42Smrg FcVStackPushExpr (parse, FcVStackExpr, expr); 15762c393a42Smrg} 15772c393a42Smrg 15782c393a42Smrg/* 15792c393a42Smrg * This builds a a unary operator, it consumes only 15802c393a42Smrg * a single operand 15812c393a42Smrg */ 15822c393a42Smrg 15832c393a42Smrgstatic FcExpr * 15842c393a42SmrgFcPopUnary (FcConfigParse *parse, FcOp op) 15852c393a42Smrg{ 15862c393a42Smrg FcExpr *operand, *new = 0; 15872c393a42Smrg 15882c393a42Smrg if ((operand = FcPopExpr (parse))) 15892c393a42Smrg { 1590a6844aabSmrg new = FcExprCreateOp (parse->config, operand, op, 0); 15912c393a42Smrg if (!new) 15922c393a42Smrg { 15932c393a42Smrg FcExprDestroy (operand); 15942c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 15952c393a42Smrg } 15962c393a42Smrg } 15972c393a42Smrg return new; 15982c393a42Smrg} 15992c393a42Smrg 16002c393a42Smrgstatic void 16012c393a42SmrgFcParseUnary (FcConfigParse *parse, FcOp op) 16022c393a42Smrg{ 16032c393a42Smrg FcExpr *expr = FcPopUnary (parse, op); 16042c393a42Smrg if (expr) 16052c393a42Smrg FcVStackPushExpr (parse, FcVStackExpr, expr); 16062c393a42Smrg} 16072c393a42Smrg 16082c393a42Smrgstatic void 16092c393a42SmrgFcParseInclude (FcConfigParse *parse) 16102c393a42Smrg{ 16112c393a42Smrg FcChar8 *s; 16122c393a42Smrg const FcChar8 *i; 16132c393a42Smrg FcBool ignore_missing = FcFalse; 16142c393a42Smrg 1615a6844aabSmrg s = FcStrBufDoneStatic (&parse->pstack->str); 16162c393a42Smrg if (!s) 16172c393a42Smrg { 16182c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 16192c393a42Smrg return; 16202c393a42Smrg } 16212c393a42Smrg i = FcConfigGetAttribute (parse, "ignore_missing"); 16222c393a42Smrg if (i && FcConfigLexBool (parse, (FcChar8 *) i) == FcTrue) 16232c393a42Smrg ignore_missing = FcTrue; 16242c393a42Smrg if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing)) 16252c393a42Smrg parse->error = FcTrue; 1626a6844aabSmrg FcStrBufDestroy (&parse->pstack->str); 16272c393a42Smrg} 16282c393a42Smrg 16292c393a42Smrgtypedef struct _FcOpMap { 16302c393a42Smrg char name[16]; 16312c393a42Smrg FcOp op; 16322c393a42Smrg} FcOpMap; 16332c393a42Smrg 16342c393a42Smrgstatic FcOp 16352c393a42SmrgFcConfigLexOp (const FcChar8 *op, const FcOpMap *map, int nmap) 16362c393a42Smrg{ 16372c393a42Smrg int i; 16382c393a42Smrg 16392c393a42Smrg for (i = 0; i < nmap; i++) 16402c393a42Smrg if (!strcmp ((char *) op, map[i].name)) 16412c393a42Smrg return map[i].op; 16422c393a42Smrg return FcOpInvalid; 16432c393a42Smrg} 16442c393a42Smrg 16452c393a42Smrgstatic const FcOpMap fcCompareOps[] = { 16462c393a42Smrg { "eq", FcOpEqual }, 16472c393a42Smrg { "not_eq", FcOpNotEqual }, 16482c393a42Smrg { "less", FcOpLess }, 16492c393a42Smrg { "less_eq", FcOpLessEqual }, 16502c393a42Smrg { "more", FcOpMore }, 16512c393a42Smrg { "more_eq", FcOpMoreEqual }, 16522c393a42Smrg { "contains", FcOpContains }, 16532c393a42Smrg { "not_contains", FcOpNotContains } 16542c393a42Smrg}; 16552c393a42Smrg 16562c393a42Smrg#define NUM_COMPARE_OPS (int) (sizeof fcCompareOps / sizeof fcCompareOps[0]) 16572c393a42Smrg 16582c393a42Smrgstatic FcOp 16592c393a42SmrgFcConfigLexCompare (const FcChar8 *compare) 16602c393a42Smrg{ 16612c393a42Smrg return FcConfigLexOp (compare, fcCompareOps, NUM_COMPARE_OPS); 16622c393a42Smrg} 16632c393a42Smrg 16642c393a42Smrgstatic void 16652c393a42SmrgFcParseTest (FcConfigParse *parse) 16662c393a42Smrg{ 16672c393a42Smrg const FcChar8 *kind_string; 16682c393a42Smrg FcMatchKind kind; 16692c393a42Smrg const FcChar8 *qual_string; 16702c393a42Smrg FcQual qual; 16712c393a42Smrg const FcChar8 *name; 16722c393a42Smrg const FcChar8 *compare_string; 16732c393a42Smrg FcOp compare; 16742c393a42Smrg FcExpr *expr; 16752c393a42Smrg FcTest *test; 16762c393a42Smrg 16772c393a42Smrg kind_string = FcConfigGetAttribute (parse, "target"); 16782c393a42Smrg if (!kind_string) 16792c393a42Smrg kind = FcMatchDefault; 16802c393a42Smrg else 16812c393a42Smrg { 16822c393a42Smrg if (!strcmp ((char *) kind_string, "pattern")) 16832c393a42Smrg kind = FcMatchPattern; 16842c393a42Smrg else if (!strcmp ((char *) kind_string, "font")) 16852c393a42Smrg kind = FcMatchFont; 16862c393a42Smrg else if (!strcmp ((char *) kind_string, "scan")) 16872c393a42Smrg kind = FcMatchScan; 16882c393a42Smrg else if (!strcmp ((char *) kind_string, "default")) 16892c393a42Smrg kind = FcMatchDefault; 16902c393a42Smrg else 16912c393a42Smrg { 16922c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "invalid test target \"%s\"", kind_string); 16932c393a42Smrg return; 16942c393a42Smrg } 16952c393a42Smrg } 16962c393a42Smrg qual_string = FcConfigGetAttribute (parse, "qual"); 16972c393a42Smrg if (!qual_string) 16982c393a42Smrg qual = FcQualAny; 16992c393a42Smrg else 17002c393a42Smrg { 17012c393a42Smrg if (!strcmp ((char *) qual_string, "any")) 17022c393a42Smrg qual = FcQualAny; 17032c393a42Smrg else if (!strcmp ((char *) qual_string, "all")) 17042c393a42Smrg qual = FcQualAll; 17052c393a42Smrg else if (!strcmp ((char *) qual_string, "first")) 17062c393a42Smrg qual = FcQualFirst; 17072c393a42Smrg else if (!strcmp ((char *) qual_string, "not_first")) 17082c393a42Smrg qual = FcQualNotFirst; 17092c393a42Smrg else 17102c393a42Smrg { 17112c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "invalid test qual \"%s\"", qual_string); 17122c393a42Smrg return; 17132c393a42Smrg } 17142c393a42Smrg } 17152c393a42Smrg name = FcConfigGetAttribute (parse, "name"); 17162c393a42Smrg if (!name) 17172c393a42Smrg { 17182c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "missing test name"); 17192c393a42Smrg return; 17202c393a42Smrg } 17212c393a42Smrg compare_string = FcConfigGetAttribute (parse, "compare"); 17222c393a42Smrg if (!compare_string) 17232c393a42Smrg compare = FcOpEqual; 17242c393a42Smrg else 17252c393a42Smrg { 17262c393a42Smrg compare = FcConfigLexCompare (compare_string); 17272c393a42Smrg if (compare == FcOpInvalid) 17282c393a42Smrg { 17292c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "invalid test compare \"%s\"", compare_string); 17302c393a42Smrg return; 17312c393a42Smrg } 17322c393a42Smrg } 17332c393a42Smrg expr = FcPopBinary (parse, FcOpComma); 17342c393a42Smrg if (!expr) 17352c393a42Smrg { 17362c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "missing test expression"); 17372c393a42Smrg return; 17382c393a42Smrg } 17392c393a42Smrg test = FcTestCreate (parse, kind, qual, name, compare, expr); 17402c393a42Smrg if (!test) 17412c393a42Smrg { 17422c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 17432c393a42Smrg return; 17442c393a42Smrg } 17452c393a42Smrg FcVStackPushTest (parse, test); 17462c393a42Smrg} 17472c393a42Smrg 17482c393a42Smrgstatic const FcOpMap fcModeOps[] = { 17492c393a42Smrg { "assign", FcOpAssign }, 17502c393a42Smrg { "assign_replace", FcOpAssignReplace }, 17512c393a42Smrg { "prepend", FcOpPrepend }, 17522c393a42Smrg { "prepend_first", FcOpPrependFirst }, 17532c393a42Smrg { "append", FcOpAppend }, 17542c393a42Smrg { "append_last", FcOpAppendLast }, 17552c393a42Smrg}; 17562c393a42Smrg 17572c393a42Smrg#define NUM_MODE_OPS (int) (sizeof fcModeOps / sizeof fcModeOps[0]) 17582c393a42Smrg 17592c393a42Smrgstatic FcOp 17602c393a42SmrgFcConfigLexMode (const FcChar8 *mode) 17612c393a42Smrg{ 17622c393a42Smrg return FcConfigLexOp (mode, fcModeOps, NUM_MODE_OPS); 17632c393a42Smrg} 17642c393a42Smrg 17652c393a42Smrgstatic void 17662c393a42SmrgFcParseEdit (FcConfigParse *parse) 17672c393a42Smrg{ 17682c393a42Smrg const FcChar8 *name; 17692c393a42Smrg const FcChar8 *mode_string; 17702c393a42Smrg FcOp mode; 17712c393a42Smrg FcValueBinding binding; 17722c393a42Smrg FcExpr *expr; 17732c393a42Smrg FcEdit *edit; 17742c393a42Smrg 17752c393a42Smrg name = FcConfigGetAttribute (parse, "name"); 17762c393a42Smrg if (!name) 17772c393a42Smrg { 17782c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "missing edit name"); 17792c393a42Smrg return; 17802c393a42Smrg } 17812c393a42Smrg mode_string = FcConfigGetAttribute (parse, "mode"); 17822c393a42Smrg if (!mode_string) 17832c393a42Smrg mode = FcOpAssign; 17842c393a42Smrg else 17852c393a42Smrg { 17862c393a42Smrg mode = FcConfigLexMode (mode_string); 17872c393a42Smrg if (mode == FcOpInvalid) 17882c393a42Smrg { 17892c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "invalid edit mode \"%s\"", mode_string); 17902c393a42Smrg return; 17912c393a42Smrg } 17922c393a42Smrg } 17932c393a42Smrg if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding)) 17942c393a42Smrg return; 17952c393a42Smrg 17962c393a42Smrg expr = FcPopBinary (parse, FcOpComma); 17972c393a42Smrg edit = FcEditCreate (parse, FcObjectFromName ((char *) name), 17982c393a42Smrg mode, expr, binding); 17992c393a42Smrg if (!edit) 18002c393a42Smrg { 18012c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 18022c393a42Smrg FcExprDestroy (expr); 18032c393a42Smrg return; 18042c393a42Smrg } 18052c393a42Smrg if (!FcVStackPushEdit (parse, edit)) 18062c393a42Smrg FcEditDestroy (edit); 18072c393a42Smrg} 18082c393a42Smrg 18092c393a42Smrgstatic void 18102c393a42SmrgFcParseMatch (FcConfigParse *parse) 18112c393a42Smrg{ 18122c393a42Smrg const FcChar8 *kind_name; 18132c393a42Smrg FcMatchKind kind; 18142c393a42Smrg FcTest *test = 0; 18152c393a42Smrg FcEdit *edit = 0; 18162c393a42Smrg FcVStack *vstack; 18172c393a42Smrg 18182c393a42Smrg kind_name = FcConfigGetAttribute (parse, "target"); 18192c393a42Smrg if (!kind_name) 18202c393a42Smrg kind = FcMatchPattern; 18212c393a42Smrg else 18222c393a42Smrg { 18232c393a42Smrg if (!strcmp ((char *) kind_name, "pattern")) 18242c393a42Smrg kind = FcMatchPattern; 18252c393a42Smrg else if (!strcmp ((char *) kind_name, "font")) 18262c393a42Smrg kind = FcMatchFont; 18272c393a42Smrg else if (!strcmp ((char *) kind_name, "scan")) 18282c393a42Smrg kind = FcMatchScan; 18292c393a42Smrg else 18302c393a42Smrg { 18312c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "invalid match target \"%s\"", kind_name); 18322c393a42Smrg return; 18332c393a42Smrg } 18342c393a42Smrg } 1835a6844aabSmrg while ((vstack = FcVStackPeek (parse))) 18362c393a42Smrg { 18372c393a42Smrg switch (vstack->tag) { 18382c393a42Smrg case FcVStackTest: 18392c393a42Smrg vstack->u.test->next = test; 18402c393a42Smrg test = vstack->u.test; 18412c393a42Smrg vstack->tag = FcVStackNone; 18422c393a42Smrg break; 18432c393a42Smrg case FcVStackEdit: 18442c393a42Smrg vstack->u.edit->next = edit; 18452c393a42Smrg edit = vstack->u.edit; 18462c393a42Smrg vstack->tag = FcVStackNone; 18472c393a42Smrg if (kind == FcMatchScan && edit->object > FC_MAX_BASE_OBJECT) 18482c393a42Smrg { 18492c393a42Smrg FcConfigMessage (parse, FcSevereError, 18502c393a42Smrg "<match target=\"scan\"> cannot edit user-defined object \"%s\"", 18512c393a42Smrg FcObjectName(edit->object)); 18522c393a42Smrg } 18532c393a42Smrg break; 18542c393a42Smrg default: 18552c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "invalid match element"); 18562c393a42Smrg break; 18572c393a42Smrg } 1858a6844aabSmrg FcVStackPopAndDestroy (parse); 18592c393a42Smrg } 18602c393a42Smrg if (!FcConfigAddEdit (parse->config, test, edit, kind)) 18612c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 18622c393a42Smrg} 18632c393a42Smrg 18642c393a42Smrgstatic void 18652c393a42SmrgFcParseAcceptRejectFont (FcConfigParse *parse, FcElement element) 18662c393a42Smrg{ 18672c393a42Smrg FcVStack *vstack; 18682c393a42Smrg 1869a6844aabSmrg while ((vstack = FcVStackPeek (parse))) 18702c393a42Smrg { 18712c393a42Smrg switch (vstack->tag) { 18722c393a42Smrg case FcVStackGlob: 18732c393a42Smrg if (!FcConfigGlobAdd (parse->config, 18742c393a42Smrg vstack->u.string, 18752c393a42Smrg element == FcElementAcceptfont)) 18762c393a42Smrg { 18772c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 18782c393a42Smrg } 18792c393a42Smrg break; 18802c393a42Smrg case FcVStackPattern: 18812c393a42Smrg if (!FcConfigPatternsAdd (parse->config, 18822c393a42Smrg vstack->u.pattern, 18832c393a42Smrg element == FcElementAcceptfont)) 18842c393a42Smrg { 18852c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 18862c393a42Smrg } 18872c393a42Smrg else 18882c393a42Smrg vstack->tag = FcVStackNone; 18892c393a42Smrg break; 18902c393a42Smrg default: 18912c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "bad font selector"); 18922c393a42Smrg break; 18932c393a42Smrg } 1894a6844aabSmrg FcVStackPopAndDestroy (parse); 18952c393a42Smrg } 18962c393a42Smrg} 18972c393a42Smrg 18982c393a42Smrg 18992c393a42Smrgstatic FcValue 19002c393a42SmrgFcPopValue (FcConfigParse *parse) 19012c393a42Smrg{ 1902a6844aabSmrg FcVStack *vstack = FcVStackPeek (parse); 19032c393a42Smrg FcValue value; 19042c393a42Smrg 19052c393a42Smrg value.type = FcTypeVoid; 19062c393a42Smrg 19072c393a42Smrg if (!vstack) 19082c393a42Smrg return value; 19092c393a42Smrg 19102c393a42Smrg switch (vstack->tag) { 19112c393a42Smrg case FcVStackString: 1912a6844aabSmrg value.u.s = FcStrStaticName (vstack->u.string); 19132c393a42Smrg if (value.u.s) 19142c393a42Smrg value.type = FcTypeString; 19152c393a42Smrg break; 19162c393a42Smrg case FcVStackConstant: 19172c393a42Smrg if (FcNameConstant (vstack->u.string, &value.u.i)) 19182c393a42Smrg value.type = FcTypeInteger; 19192c393a42Smrg break; 19202c393a42Smrg case FcVStackInteger: 19212c393a42Smrg value.u.i = vstack->u.integer; 19222c393a42Smrg value.type = FcTypeInteger; 19232c393a42Smrg break; 19242c393a42Smrg case FcVStackDouble: 19252c393a42Smrg value.u.d = vstack->u._double; 19262c393a42Smrg value.type = FcTypeInteger; 19272c393a42Smrg break; 19282c393a42Smrg case FcVStackMatrix: 19292c393a42Smrg value.u.m = FcMatrixCopy (vstack->u.matrix); 19302c393a42Smrg if (value.u.m) 19312c393a42Smrg value.type = FcTypeMatrix; 19322c393a42Smrg break; 19332c393a42Smrg case FcVStackBool: 1934a6844aabSmrg value.u.b = vstack->u.bool_; 19352c393a42Smrg value.type = FcTypeBool; 19362c393a42Smrg break; 19372c393a42Smrg default: 19382c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "unknown pattern element %d", 19392c393a42Smrg vstack->tag); 19402c393a42Smrg break; 19412c393a42Smrg } 1942a6844aabSmrg FcVStackPopAndDestroy (parse); 19432c393a42Smrg 19442c393a42Smrg return value; 19452c393a42Smrg} 19462c393a42Smrg 19472c393a42Smrgstatic void 19482c393a42SmrgFcParsePatelt (FcConfigParse *parse) 19492c393a42Smrg{ 19502c393a42Smrg FcValue value; 19512c393a42Smrg FcPattern *pattern = FcPatternCreate (); 19522c393a42Smrg const char *name; 19532c393a42Smrg 19542c393a42Smrg if (!pattern) 19552c393a42Smrg { 19562c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 19572c393a42Smrg return; 19582c393a42Smrg } 19592c393a42Smrg 19602c393a42Smrg name = (char *) FcConfigGetAttribute (parse, "name"); 19612c393a42Smrg if (!name) 19622c393a42Smrg { 19632c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "missing pattern element name"); 19642c393a42Smrg FcPatternDestroy (pattern); 19652c393a42Smrg return; 19662c393a42Smrg } 19672c393a42Smrg 19682c393a42Smrg for (;;) 19692c393a42Smrg { 19702c393a42Smrg value = FcPopValue (parse); 19712c393a42Smrg if (value.type == FcTypeVoid) 19722c393a42Smrg break; 19732c393a42Smrg if (!FcPatternAdd (pattern, name, value, FcTrue)) 19742c393a42Smrg { 19752c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 1976a6844aabSmrg FcValueDestroy(value); 19772c393a42Smrg break; 19782c393a42Smrg } 1979a6844aabSmrg FcValueDestroy(value); 19802c393a42Smrg } 19812c393a42Smrg 19822c393a42Smrg FcVStackPushPattern (parse, pattern); 19832c393a42Smrg} 19842c393a42Smrg 19852c393a42Smrgstatic void 19862c393a42SmrgFcParsePattern (FcConfigParse *parse) 19872c393a42Smrg{ 19882c393a42Smrg FcVStack *vstack; 19892c393a42Smrg FcPattern *pattern = FcPatternCreate (); 19902c393a42Smrg 19912c393a42Smrg if (!pattern) 19922c393a42Smrg { 19932c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 19942c393a42Smrg return; 19952c393a42Smrg } 19962c393a42Smrg 1997a6844aabSmrg while ((vstack = FcVStackPeek (parse))) 19982c393a42Smrg { 19992c393a42Smrg switch (vstack->tag) { 20002c393a42Smrg case FcVStackPattern: 20012c393a42Smrg if (!FcPatternAppend (pattern, vstack->u.pattern)) 20022c393a42Smrg { 20032c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 20042c393a42Smrg FcPatternDestroy (pattern); 20052c393a42Smrg return; 20062c393a42Smrg } 20072c393a42Smrg break; 20082c393a42Smrg default: 20092c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "unknown pattern element"); 20102c393a42Smrg break; 20112c393a42Smrg } 2012a6844aabSmrg FcVStackPopAndDestroy (parse); 20132c393a42Smrg } 20142c393a42Smrg 20152c393a42Smrg FcVStackPushPattern (parse, pattern); 20162c393a42Smrg} 20172c393a42Smrg 20182c393a42Smrgstatic void 20192c393a42SmrgFcEndElement(void *userData, const XML_Char *name) 20202c393a42Smrg{ 20212c393a42Smrg FcConfigParse *parse = userData; 20222c393a42Smrg FcChar8 *data; 2023a6844aabSmrg#ifdef _WIN32 2024a6844aabSmrg FcChar8 buffer[1000]; 2025a6844aabSmrg#endif 2026a6844aabSmrg 20272c393a42Smrg if (!parse->pstack) 20282c393a42Smrg return; 20292c393a42Smrg switch (parse->pstack->element) { 20302c393a42Smrg case FcElementNone: 20312c393a42Smrg break; 20322c393a42Smrg case FcElementFontconfig: 20332c393a42Smrg break; 20342c393a42Smrg case FcElementDir: 2035a6844aabSmrg data = FcStrBufDoneStatic (&parse->pstack->str); 20362c393a42Smrg if (!data) 20372c393a42Smrg { 20382c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 20392c393a42Smrg break; 20402c393a42Smrg } 20412c393a42Smrg#ifdef _WIN32 20422c393a42Smrg if (strcmp (data, "CUSTOMFONTDIR") == 0) 20432c393a42Smrg { 2044a6844aabSmrg char *p; 2045a6844aabSmrg data = buffer; 2046a6844aabSmrg if (!GetModuleFileName (NULL, buffer, sizeof (buffer) - 20)) 20472c393a42Smrg { 2048a6844aabSmrg FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed"); 20492c393a42Smrg break; 20502c393a42Smrg } 2051a6844aabSmrg /* 2052a6844aabSmrg * Must use the multi-byte aware function to search 2053a6844aabSmrg * for backslash because East Asian double-byte code 2054a6844aabSmrg * pages have characters with backslash as the second 2055a6844aabSmrg * byte. 2056a6844aabSmrg */ 2057a6844aabSmrg p = _mbsrchr (data, '\\'); 2058a6844aabSmrg if (p) *p = '\0'; 2059a6844aabSmrg strcat (data, "\\fonts"); 2060a6844aabSmrg } 2061a6844aabSmrg else if (strcmp (data, "APPSHAREFONTDIR") == 0) 2062a6844aabSmrg { 2063a6844aabSmrg char *p; 2064a6844aabSmrg data = buffer; 2065a6844aabSmrg if (!GetModuleFileName (NULL, buffer, sizeof (buffer) - 20)) 20662c393a42Smrg { 20672c393a42Smrg FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed"); 20682c393a42Smrg break; 20692c393a42Smrg } 2070a6844aabSmrg p = _mbsrchr (data, '\\'); 20712c393a42Smrg if (p) *p = '\0'; 2072a6844aabSmrg strcat (data, "\\..\\share\\fonts"); 20732c393a42Smrg } 20742c393a42Smrg else if (strcmp (data, "WINDOWSFONTDIR") == 0) 20752c393a42Smrg { 20762c393a42Smrg int rc; 2077a6844aabSmrg data = buffer; 2078a6844aabSmrg#if _WIN32_WINNT >= 0x0500 2079a6844aabSmrg rc = GetSystemWindowsDirectory (buffer, sizeof (buffer) - 20); 2080a6844aabSmrg#else 2081a6844aabSmrg rc = GetWindowsDirectory (buffer, sizeof (buffer) - 20); 2082a6844aabSmrg#endif 2083a6844aabSmrg if (rc == 0 || rc > sizeof (buffer) - 20) 20842c393a42Smrg { 2085a6844aabSmrg FcConfigMessage (parse, FcSevereError, "GetSystemWindowsDirectory failed"); 20862c393a42Smrg break; 20872c393a42Smrg } 20882c393a42Smrg if (data [strlen (data) - 1] != '\\') 20892c393a42Smrg strcat (data, "\\"); 20902c393a42Smrg strcat (data, "fonts"); 20912c393a42Smrg } 20922c393a42Smrg#endif 20932c393a42Smrg if (strlen ((char *) data) == 0) 20942c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "empty font directory name ignored"); 20952c393a42Smrg else if (!FcStrUsesHome (data) || FcConfigHome ()) 20962c393a42Smrg { 20972c393a42Smrg if (!FcConfigAddDir (parse->config, data)) 20982c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", data); 20992c393a42Smrg } 2100a6844aabSmrg FcStrBufDestroy (&parse->pstack->str); 21012c393a42Smrg break; 21022c393a42Smrg case FcElementCacheDir: 21032c393a42Smrg data = FcStrBufDone (&parse->pstack->str); 21042c393a42Smrg if (!data) 21052c393a42Smrg { 21062c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 21072c393a42Smrg break; 21082c393a42Smrg } 21092c393a42Smrg#ifdef _WIN32 21102c393a42Smrg if (strcmp (data, "WINDOWSTEMPDIR_FONTCONFIG_CACHE") == 0) 21112c393a42Smrg { 21122c393a42Smrg int rc; 21132c393a42Smrg FcStrFree (data); 21142c393a42Smrg data = malloc (1000); 21152c393a42Smrg if (!data) 21162c393a42Smrg { 21172c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 21182c393a42Smrg break; 21192c393a42Smrg } 21202c393a42Smrg FcMemAlloc (FC_MEM_STRING, 1000); 21212c393a42Smrg rc = GetTempPath (800, data); 21222c393a42Smrg if (rc == 0 || rc > 800) 21232c393a42Smrg { 2124a6844aabSmrg FcConfigMessage (parse, FcSevereError, "GetTempPath failed"); 21252c393a42Smrg FcStrFree (data); 21262c393a42Smrg break; 21272c393a42Smrg } 21282c393a42Smrg if (data [strlen (data) - 1] != '\\') 21292c393a42Smrg strcat (data, "\\"); 21302c393a42Smrg strcat (data, "fontconfig\\cache"); 21312c393a42Smrg } 21322c393a42Smrg#endif 21332c393a42Smrg if (!FcStrUsesHome (data) || FcConfigHome ()) 21342c393a42Smrg { 21352c393a42Smrg if (!FcConfigAddCacheDir (parse->config, data)) 21362c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory; cannot add cache directory %s", data); 21372c393a42Smrg } 21382c393a42Smrg FcStrFree (data); 21392c393a42Smrg break; 21402c393a42Smrg 21412c393a42Smrg case FcElementCache: 2142a6844aabSmrg data = FcStrBufDoneStatic (&parse->pstack->str); 21432c393a42Smrg if (!data) 21442c393a42Smrg { 21452c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 21462c393a42Smrg break; 21472c393a42Smrg } 21482c393a42Smrg /* discard this data; no longer used */ 2149a6844aabSmrg FcStrBufDestroy (&parse->pstack->str); 21502c393a42Smrg break; 21512c393a42Smrg case FcElementInclude: 21522c393a42Smrg FcParseInclude (parse); 21532c393a42Smrg break; 21542c393a42Smrg case FcElementConfig: 21552c393a42Smrg break; 21562c393a42Smrg case FcElementMatch: 21572c393a42Smrg FcParseMatch (parse); 21582c393a42Smrg break; 21592c393a42Smrg case FcElementAlias: 21602c393a42Smrg FcParseAlias (parse); 21612c393a42Smrg break; 21622c393a42Smrg 21632c393a42Smrg case FcElementBlank: 21642c393a42Smrg FcParseBlank (parse); 21652c393a42Smrg break; 21662c393a42Smrg case FcElementRescan: 21672c393a42Smrg FcParseRescan (parse); 21682c393a42Smrg break; 21692c393a42Smrg 21702c393a42Smrg case FcElementPrefer: 21712c393a42Smrg FcParseFamilies (parse, FcVStackPrefer); 21722c393a42Smrg break; 21732c393a42Smrg case FcElementAccept: 21742c393a42Smrg FcParseFamilies (parse, FcVStackAccept); 21752c393a42Smrg break; 21762c393a42Smrg case FcElementDefault: 21772c393a42Smrg FcParseFamilies (parse, FcVStackDefault); 21782c393a42Smrg break; 21792c393a42Smrg case FcElementFamily: 21802c393a42Smrg FcParseFamily (parse); 21812c393a42Smrg break; 21822c393a42Smrg 21832c393a42Smrg case FcElementTest: 21842c393a42Smrg FcParseTest (parse); 21852c393a42Smrg break; 21862c393a42Smrg case FcElementEdit: 21872c393a42Smrg FcParseEdit (parse); 21882c393a42Smrg break; 21892c393a42Smrg 21902c393a42Smrg case FcElementInt: 21912c393a42Smrg FcParseInt (parse); 21922c393a42Smrg break; 21932c393a42Smrg case FcElementDouble: 21942c393a42Smrg FcParseDouble (parse); 21952c393a42Smrg break; 21962c393a42Smrg case FcElementString: 21972c393a42Smrg FcParseString (parse, FcVStackString); 21982c393a42Smrg break; 21992c393a42Smrg case FcElementMatrix: 22002c393a42Smrg FcParseMatrix (parse); 22012c393a42Smrg break; 22022c393a42Smrg case FcElementBool: 22032c393a42Smrg FcParseBool (parse); 22042c393a42Smrg break; 22052c393a42Smrg case FcElementCharset: 22062c393a42Smrg/* FcParseCharset (parse); */ 22072c393a42Smrg break; 22082c393a42Smrg case FcElementSelectfont: 22092c393a42Smrg break; 22102c393a42Smrg case FcElementAcceptfont: 22112c393a42Smrg case FcElementRejectfont: 22122c393a42Smrg FcParseAcceptRejectFont (parse, parse->pstack->element); 22132c393a42Smrg break; 22142c393a42Smrg case FcElementGlob: 22152c393a42Smrg FcParseString (parse, FcVStackGlob); 22162c393a42Smrg break; 22172c393a42Smrg case FcElementPattern: 22182c393a42Smrg FcParsePattern (parse); 22192c393a42Smrg break; 22202c393a42Smrg case FcElementPatelt: 22212c393a42Smrg FcParsePatelt (parse); 22222c393a42Smrg break; 22232c393a42Smrg case FcElementName: 22242c393a42Smrg FcParseString (parse, FcVStackField); 22252c393a42Smrg break; 22262c393a42Smrg case FcElementConst: 22272c393a42Smrg FcParseString (parse, FcVStackConstant); 22282c393a42Smrg break; 22292c393a42Smrg case FcElementOr: 22302c393a42Smrg FcParseBinary (parse, FcOpOr); 22312c393a42Smrg break; 22322c393a42Smrg case FcElementAnd: 22332c393a42Smrg FcParseBinary (parse, FcOpAnd); 22342c393a42Smrg break; 22352c393a42Smrg case FcElementEq: 22362c393a42Smrg FcParseBinary (parse, FcOpEqual); 22372c393a42Smrg break; 22382c393a42Smrg case FcElementNotEq: 22392c393a42Smrg FcParseBinary (parse, FcOpNotEqual); 22402c393a42Smrg break; 22412c393a42Smrg case FcElementLess: 22422c393a42Smrg FcParseBinary (parse, FcOpLess); 22432c393a42Smrg break; 22442c393a42Smrg case FcElementLessEq: 22452c393a42Smrg FcParseBinary (parse, FcOpLessEqual); 22462c393a42Smrg break; 22472c393a42Smrg case FcElementMore: 22482c393a42Smrg FcParseBinary (parse, FcOpMore); 22492c393a42Smrg break; 22502c393a42Smrg case FcElementMoreEq: 22512c393a42Smrg FcParseBinary (parse, FcOpMoreEqual); 22522c393a42Smrg break; 22532c393a42Smrg case FcElementContains: 22542c393a42Smrg FcParseBinary (parse, FcOpContains); 22552c393a42Smrg break; 22562c393a42Smrg case FcElementNotContains: 22572c393a42Smrg FcParseBinary (parse, FcOpNotContains); 22582c393a42Smrg break; 22592c393a42Smrg case FcElementPlus: 22602c393a42Smrg FcParseBinary (parse, FcOpPlus); 22612c393a42Smrg break; 22622c393a42Smrg case FcElementMinus: 22632c393a42Smrg FcParseBinary (parse, FcOpMinus); 22642c393a42Smrg break; 22652c393a42Smrg case FcElementTimes: 22662c393a42Smrg FcParseBinary (parse, FcOpTimes); 22672c393a42Smrg break; 22682c393a42Smrg case FcElementDivide: 22692c393a42Smrg FcParseBinary (parse, FcOpDivide); 22702c393a42Smrg break; 22712c393a42Smrg case FcElementNot: 22722c393a42Smrg FcParseUnary (parse, FcOpNot); 22732c393a42Smrg break; 22742c393a42Smrg case FcElementIf: 22752c393a42Smrg FcParseBinary (parse, FcOpQuest); 22762c393a42Smrg break; 22772c393a42Smrg case FcElementFloor: 22782c393a42Smrg FcParseUnary (parse, FcOpFloor); 22792c393a42Smrg break; 22802c393a42Smrg case FcElementCeil: 22812c393a42Smrg FcParseUnary (parse, FcOpCeil); 22822c393a42Smrg break; 22832c393a42Smrg case FcElementRound: 22842c393a42Smrg FcParseUnary (parse, FcOpRound); 22852c393a42Smrg break; 22862c393a42Smrg case FcElementTrunc: 22872c393a42Smrg FcParseUnary (parse, FcOpTrunc); 22882c393a42Smrg break; 22892c393a42Smrg case FcElementUnknown: 22902c393a42Smrg break; 22912c393a42Smrg } 22922c393a42Smrg (void) FcPStackPop (parse); 22932c393a42Smrg} 22942c393a42Smrg 22952c393a42Smrgstatic void 22962c393a42SmrgFcCharacterData (void *userData, const XML_Char *s, int len) 22972c393a42Smrg{ 22982c393a42Smrg FcConfigParse *parse = userData; 22992c393a42Smrg 23002c393a42Smrg if (!parse->pstack) 23012c393a42Smrg return; 23022c393a42Smrg if (!FcStrBufData (&parse->pstack->str, (FcChar8 *) s, len)) 23032c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 23042c393a42Smrg} 23052c393a42Smrg 23062c393a42Smrgstatic void 23072c393a42SmrgFcStartDoctypeDecl (void *userData, 23082c393a42Smrg const XML_Char *doctypeName, 23092c393a42Smrg const XML_Char *sysid, 23102c393a42Smrg const XML_Char *pubid, 23112c393a42Smrg int has_internal_subset) 23122c393a42Smrg{ 23132c393a42Smrg FcConfigParse *parse = userData; 23142c393a42Smrg 23152c393a42Smrg if (strcmp ((char *) doctypeName, "fontconfig") != 0) 23162c393a42Smrg FcConfigMessage (parse, FcSevereError, "invalid doctype \"%s\"", doctypeName); 23172c393a42Smrg} 23182c393a42Smrg 23192c393a42Smrg#ifdef ENABLE_LIBXML2 23202c393a42Smrg 23212c393a42Smrgstatic void 23222c393a42SmrgFcInternalSubsetDecl (void *userData, 23232c393a42Smrg const XML_Char *doctypeName, 23242c393a42Smrg const XML_Char *sysid, 23252c393a42Smrg const XML_Char *pubid) 23262c393a42Smrg{ 23272c393a42Smrg FcStartDoctypeDecl (userData, doctypeName, sysid, pubid, 1); 23282c393a42Smrg} 23292c393a42Smrg 23302c393a42Smrgstatic void 23312c393a42SmrgFcExternalSubsetDecl (void *userData, 23322c393a42Smrg const XML_Char *doctypeName, 23332c393a42Smrg const XML_Char *sysid, 23342c393a42Smrg const XML_Char *pubid) 23352c393a42Smrg{ 23362c393a42Smrg FcStartDoctypeDecl (userData, doctypeName, sysid, pubid, 0); 23372c393a42Smrg} 23382c393a42Smrg 23392c393a42Smrg#else /* ENABLE_LIBXML2 */ 23402c393a42Smrg 23412c393a42Smrgstatic void 23422c393a42SmrgFcEndDoctypeDecl (void *userData) 23432c393a42Smrg{ 23442c393a42Smrg} 23452c393a42Smrg 23462c393a42Smrg#endif /* ENABLE_LIBXML2 */ 23472c393a42Smrg 23482c393a42Smrgstatic int 23492c393a42SmrgFcSortCmpStr (const void *a, const void *b) 23502c393a42Smrg{ 23512c393a42Smrg const FcChar8 *as = *((FcChar8 **) a); 23522c393a42Smrg const FcChar8 *bs = *((FcChar8 **) b); 23532c393a42Smrg return FcStrCmp (as, bs); 23542c393a42Smrg} 23552c393a42Smrg 23562c393a42Smrgstatic FcBool 23572c393a42SmrgFcConfigParseAndLoadDir (FcConfig *config, 23582c393a42Smrg const FcChar8 *name, 23592c393a42Smrg const FcChar8 *dir, 23602c393a42Smrg FcBool complain) 23612c393a42Smrg{ 23622c393a42Smrg DIR *d; 23632c393a42Smrg struct dirent *e; 23642c393a42Smrg FcBool ret = FcTrue; 23652c393a42Smrg FcChar8 *file; 23662c393a42Smrg FcChar8 *base; 23672c393a42Smrg FcStrSet *files; 23682c393a42Smrg 23692c393a42Smrg d = opendir ((char *) dir); 23702c393a42Smrg if (!d) 23712c393a42Smrg { 23722c393a42Smrg if (complain) 23732c393a42Smrg FcConfigMessage (0, FcSevereError, "Cannot open config dir \"%s\"", 23742c393a42Smrg name); 23752c393a42Smrg ret = FcFalse; 23762c393a42Smrg goto bail0; 23772c393a42Smrg } 23782c393a42Smrg /* freed below */ 23792c393a42Smrg file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1); 23802c393a42Smrg if (!file) 23812c393a42Smrg { 23822c393a42Smrg ret = FcFalse; 23832c393a42Smrg goto bail1; 23842c393a42Smrg } 23852c393a42Smrg 23862c393a42Smrg strcpy ((char *) file, (char *) dir); 23872c393a42Smrg strcat ((char *) file, "/"); 23882c393a42Smrg base = file + strlen ((char *) file); 23892c393a42Smrg 23902c393a42Smrg files = FcStrSetCreate (); 23912c393a42Smrg if (!files) 23922c393a42Smrg { 23932c393a42Smrg ret = FcFalse; 23942c393a42Smrg goto bail2; 23952c393a42Smrg } 23962c393a42Smrg 23972c393a42Smrg if (FcDebug () & FC_DBG_CONFIG) 23982c393a42Smrg printf ("\tScanning config dir %s\n", dir); 23992c393a42Smrg 24002c393a42Smrg while (ret && (e = readdir (d))) 24012c393a42Smrg { 24022c393a42Smrg int d_len; 24032c393a42Smrg#define TAIL ".conf" 24042c393a42Smrg#define TAIL_LEN 5 24052c393a42Smrg /* 24062c393a42Smrg * Add all files of the form [0-9]*.conf 24072c393a42Smrg */ 24082c393a42Smrg if ('0' <= e->d_name[0] && e->d_name[0] <= '9' && 24092c393a42Smrg (d_len = strlen (e->d_name)) < FC_MAX_FILE_LEN && 24102c393a42Smrg d_len > TAIL_LEN && 24112c393a42Smrg strcmp (e->d_name + d_len - TAIL_LEN, TAIL) == 0) 24122c393a42Smrg { 24132c393a42Smrg strcpy ((char *) base, (char *) e->d_name); 24142c393a42Smrg if (!FcStrSetAdd (files, file)) 24152c393a42Smrg { 24162c393a42Smrg ret = FcFalse; 24172c393a42Smrg goto bail3; 24182c393a42Smrg } 24192c393a42Smrg } 24202c393a42Smrg } 24212c393a42Smrg if (ret) 24222c393a42Smrg { 24232c393a42Smrg int i; 24242c393a42Smrg qsort (files->strs, files->num, sizeof (FcChar8 *), 24252c393a42Smrg (int (*)(const void *, const void *)) FcSortCmpStr); 24262c393a42Smrg for (i = 0; ret && i < files->num; i++) 24272c393a42Smrg ret = FcConfigParseAndLoad (config, files->strs[i], complain); 24282c393a42Smrg } 24292c393a42Smrgbail3: 24302c393a42Smrg FcStrSetDestroy (files); 24312c393a42Smrgbail2: 24322c393a42Smrg free (file); 24332c393a42Smrgbail1: 24342c393a42Smrg closedir (d); 24352c393a42Smrgbail0: 24362c393a42Smrg return ret || !complain; 24372c393a42Smrg} 24382c393a42Smrg 24392c393a42SmrgFcBool 24402c393a42SmrgFcConfigParseAndLoad (FcConfig *config, 24412c393a42Smrg const FcChar8 *name, 24422c393a42Smrg FcBool complain) 24432c393a42Smrg{ 24442c393a42Smrg 24452c393a42Smrg XML_Parser p; 24462c393a42Smrg FcChar8 *filename; 24472c393a42Smrg int fd; 24482c393a42Smrg int len; 24492c393a42Smrg FcConfigParse parse; 24502c393a42Smrg FcBool error = FcTrue; 24512c393a42Smrg 24522c393a42Smrg#ifdef ENABLE_LIBXML2 24532c393a42Smrg xmlSAXHandler sax; 24542c393a42Smrg char buf[BUFSIZ]; 24552c393a42Smrg#else 24562c393a42Smrg void *buf; 24572c393a42Smrg#endif 24582c393a42Smrg 24592c393a42Smrg filename = FcConfigFilename (name); 24602c393a42Smrg if (!filename) 24612c393a42Smrg goto bail0; 24622c393a42Smrg 24632c393a42Smrg if (FcStrSetMember (config->configFiles, filename)) 24642c393a42Smrg { 24652c393a42Smrg FcStrFree (filename); 24662c393a42Smrg return FcTrue; 24672c393a42Smrg } 24682c393a42Smrg 24692c393a42Smrg if (!FcStrSetAdd (config->configFiles, filename)) 24702c393a42Smrg { 24712c393a42Smrg FcStrFree (filename); 24722c393a42Smrg goto bail0; 24732c393a42Smrg } 24742c393a42Smrg 24752c393a42Smrg if (FcFileIsDir (filename)) 24762c393a42Smrg { 24772c393a42Smrg FcBool ret = FcConfigParseAndLoadDir (config, name, filename, complain); 24782c393a42Smrg FcStrFree (filename); 24792c393a42Smrg return ret; 24802c393a42Smrg } 24812c393a42Smrg 24822c393a42Smrg if (FcDebug () & FC_DBG_CONFIG) 24832c393a42Smrg printf ("\tLoading config file %s\n", filename); 24842c393a42Smrg 24852c393a42Smrg fd = open ((char *) filename, O_RDONLY); 24862c393a42Smrg if (fd == -1) { 24872c393a42Smrg FcStrFree (filename); 24882c393a42Smrg goto bail0; 24892c393a42Smrg } 24902c393a42Smrg 24912c393a42Smrg#ifdef ENABLE_LIBXML2 24922c393a42Smrg memset(&sax, 0, sizeof(sax)); 24932c393a42Smrg 24942c393a42Smrg sax.internalSubset = FcInternalSubsetDecl; 24952c393a42Smrg sax.externalSubset = FcExternalSubsetDecl; 24962c393a42Smrg sax.startElement = FcStartElement; 24972c393a42Smrg sax.endElement = FcEndElement; 24982c393a42Smrg sax.characters = FcCharacterData; 24992c393a42Smrg 25002c393a42Smrg p = xmlCreatePushParserCtxt (&sax, &parse, NULL, 0, (const char *) filename); 25012c393a42Smrg#else 25022c393a42Smrg p = XML_ParserCreate ("UTF-8"); 25032c393a42Smrg#endif 25042c393a42Smrg FcStrFree (filename); 25052c393a42Smrg 25062c393a42Smrg if (!p) 25072c393a42Smrg goto bail1; 25082c393a42Smrg 25092c393a42Smrg if (!FcConfigInit (&parse, name, config, p)) 25102c393a42Smrg goto bail2; 25112c393a42Smrg 25122c393a42Smrg#ifndef ENABLE_LIBXML2 25132c393a42Smrg 25142c393a42Smrg XML_SetUserData (p, &parse); 25152c393a42Smrg 25162c393a42Smrg XML_SetDoctypeDeclHandler (p, FcStartDoctypeDecl, FcEndDoctypeDecl); 25172c393a42Smrg XML_SetElementHandler (p, FcStartElement, FcEndElement); 25182c393a42Smrg XML_SetCharacterDataHandler (p, FcCharacterData); 25192c393a42Smrg 25202c393a42Smrg#endif /* ENABLE_LIBXML2 */ 25212c393a42Smrg 25222c393a42Smrg do { 25232c393a42Smrg#ifndef ENABLE_LIBXML2 25242c393a42Smrg buf = XML_GetBuffer (p, BUFSIZ); 25252c393a42Smrg if (!buf) 25262c393a42Smrg { 25272c393a42Smrg FcConfigMessage (&parse, FcSevereError, "cannot get parse buffer"); 25282c393a42Smrg goto bail3; 25292c393a42Smrg } 25302c393a42Smrg#endif 25312c393a42Smrg len = read (fd, buf, BUFSIZ); 25322c393a42Smrg if (len < 0) 25332c393a42Smrg { 25342c393a42Smrg FcConfigMessage (&parse, FcSevereError, "failed reading config file"); 25352c393a42Smrg goto bail3; 25362c393a42Smrg } 25372c393a42Smrg 25382c393a42Smrg#ifdef ENABLE_LIBXML2 25392c393a42Smrg if (xmlParseChunk (p, buf, len, len == 0)) 25402c393a42Smrg#else 25412c393a42Smrg if (!XML_ParseBuffer (p, len, len == 0)) 25422c393a42Smrg#endif 25432c393a42Smrg { 25442c393a42Smrg FcConfigMessage (&parse, FcSevereError, "%s", 25452c393a42Smrg XML_ErrorString (XML_GetErrorCode (p))); 25462c393a42Smrg goto bail3; 25472c393a42Smrg } 25482c393a42Smrg } while (len != 0); 25492c393a42Smrg error = parse.error; 25502c393a42Smrgbail3: 25512c393a42Smrg FcConfigCleanup (&parse); 25522c393a42Smrgbail2: 25532c393a42Smrg XML_ParserFree (p); 25542c393a42Smrgbail1: 25552c393a42Smrg close (fd); 25562c393a42Smrg fd = -1; 25572c393a42Smrgbail0: 25582c393a42Smrg if (error && complain) 25592c393a42Smrg { 25602c393a42Smrg if (name) 25612c393a42Smrg FcConfigMessage (0, FcSevereError, "Cannot load config file \"%s\"", name); 25622c393a42Smrg else 25632c393a42Smrg FcConfigMessage (0, FcSevereError, "Cannot load default config file"); 25642c393a42Smrg return FcFalse; 25652c393a42Smrg } 25662c393a42Smrg return FcTrue; 25672c393a42Smrg} 25682c393a42Smrg#define __fcxml__ 25692c393a42Smrg#include "fcaliastail.h" 25702c393a42Smrg#undef __fcxml__ 2571