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