fcxml.c revision ca08ab68
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 10ca08ab68Smrg * documentation, and that the name of the author(s) not be used in 112c393a42Smrg * advertising or publicity pertaining to distribution of the software without 12ca08ab68Smrg * specific, written prior permission. The authors make 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#include <mbstring.h> 572c393a42Smrg#endif 582c393a42Smrg 59a6844aabSmrgstatic void 60a6844aabSmrgFcExprDestroy (FcExpr *e); 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 72a6844aabSmrgstatic FcExpr * 73a6844aabSmrgFcExprCreateInteger (FcConfig *config, int i) 742c393a42Smrg{ 75a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 762c393a42Smrg if (e) 772c393a42Smrg { 782c393a42Smrg e->op = FcOpInteger; 792c393a42Smrg e->u.ival = i; 802c393a42Smrg } 812c393a42Smrg return e; 822c393a42Smrg} 832c393a42Smrg 84a6844aabSmrgstatic FcExpr * 85a6844aabSmrgFcExprCreateDouble (FcConfig *config, double d) 862c393a42Smrg{ 87a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 882c393a42Smrg if (e) 892c393a42Smrg { 902c393a42Smrg e->op = FcOpDouble; 912c393a42Smrg e->u.dval = d; 922c393a42Smrg } 932c393a42Smrg return e; 942c393a42Smrg} 952c393a42Smrg 96a6844aabSmrgstatic FcExpr * 97a6844aabSmrgFcExprCreateString (FcConfig *config, const FcChar8 *s) 982c393a42Smrg{ 99a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 1002c393a42Smrg if (e) 1012c393a42Smrg { 1022c393a42Smrg e->op = FcOpString; 103ca08ab68Smrg e->u.sval = FcSharedStr (s); 1042c393a42Smrg } 1052c393a42Smrg return e; 1062c393a42Smrg} 1072c393a42Smrg 108a6844aabSmrgstatic FcExpr * 109a6844aabSmrgFcExprCreateMatrix (FcConfig *config, const FcMatrix *m) 1102c393a42Smrg{ 111a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 1122c393a42Smrg if (e) 1132c393a42Smrg { 1142c393a42Smrg e->op = FcOpMatrix; 1152c393a42Smrg e->u.mval = FcMatrixCopy (m); 1162c393a42Smrg } 1172c393a42Smrg return e; 1182c393a42Smrg} 1192c393a42Smrg 120a6844aabSmrgstatic FcExpr * 121a6844aabSmrgFcExprCreateBool (FcConfig *config, FcBool b) 1222c393a42Smrg{ 123a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 1242c393a42Smrg if (e) 1252c393a42Smrg { 1262c393a42Smrg e->op = FcOpBool; 1272c393a42Smrg e->u.bval = b; 1282c393a42Smrg } 1292c393a42Smrg return e; 1302c393a42Smrg} 1312c393a42Smrg 132ca08ab68Smrgstatic FcExpr * 133ca08ab68SmrgFcExprCreateCharSet (FcConfig *config, FcCharSet *charset) 134ca08ab68Smrg{ 135ca08ab68Smrg FcExpr *e = FcConfigAllocExpr (config); 136ca08ab68Smrg if (e) 137ca08ab68Smrg { 138ca08ab68Smrg e->op = FcOpCharSet; 139ca08ab68Smrg e->u.cval = FcCharSetCopy (charset); 140ca08ab68Smrg } 141ca08ab68Smrg return e; 142ca08ab68Smrg} 143ca08ab68Smrg 144ca08ab68Smrgstatic FcExpr * 145ca08ab68SmrgFcExprCreateLangSet (FcConfig *config, FcLangSet *langset) 146ca08ab68Smrg{ 147ca08ab68Smrg FcExpr *e = FcConfigAllocExpr (config); 148ca08ab68Smrg if (e) 149ca08ab68Smrg { 150ca08ab68Smrg e->op = FcOpLangSet; 151ca08ab68Smrg e->u.lval = FcLangSetCopy (langset); 152ca08ab68Smrg } 153ca08ab68Smrg return e; 154ca08ab68Smrg} 155ca08ab68Smrg 156a6844aabSmrgstatic FcExpr * 157a6844aabSmrgFcExprCreateField (FcConfig *config, const char *field) 1582c393a42Smrg{ 159a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 1602c393a42Smrg if (e) 1612c393a42Smrg { 1622c393a42Smrg e->op = FcOpField; 1632c393a42Smrg e->u.object = FcObjectFromName (field); 1642c393a42Smrg } 1652c393a42Smrg return e; 1662c393a42Smrg} 1672c393a42Smrg 168a6844aabSmrgstatic FcExpr * 169a6844aabSmrgFcExprCreateConst (FcConfig *config, const FcChar8 *constant) 1702c393a42Smrg{ 171a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 1722c393a42Smrg if (e) 1732c393a42Smrg { 1742c393a42Smrg e->op = FcOpConst; 175ca08ab68Smrg e->u.constant = FcSharedStr (constant); 1762c393a42Smrg } 1772c393a42Smrg return e; 1782c393a42Smrg} 1792c393a42Smrg 180a6844aabSmrgstatic FcExpr * 181a6844aabSmrgFcExprCreateOp (FcConfig *config, FcExpr *left, FcOp op, FcExpr *right) 1822c393a42Smrg{ 183a6844aabSmrg FcExpr *e = FcConfigAllocExpr (config); 1842c393a42Smrg if (e) 1852c393a42Smrg { 1862c393a42Smrg e->op = op; 1872c393a42Smrg e->u.tree.left = left; 1882c393a42Smrg e->u.tree.right = right; 1892c393a42Smrg } 1902c393a42Smrg return e; 1912c393a42Smrg} 1922c393a42Smrg 193a6844aabSmrgstatic void 1942c393a42SmrgFcExprDestroy (FcExpr *e) 1952c393a42Smrg{ 1962c393a42Smrg if (!e) 1972c393a42Smrg return; 198ca08ab68Smrg switch (FC_OP_GET_OP (e->op)) { 1992c393a42Smrg case FcOpInteger: 2002c393a42Smrg break; 2012c393a42Smrg case FcOpDouble: 2022c393a42Smrg break; 2032c393a42Smrg case FcOpString: 204ca08ab68Smrg FcSharedStrFree (e->u.sval); 2052c393a42Smrg break; 2062c393a42Smrg case FcOpMatrix: 2072c393a42Smrg FcMatrixFree (e->u.mval); 2082c393a42Smrg break; 209ca08ab68Smrg case FcOpRange: 210ca08ab68Smrg break; 2112c393a42Smrg case FcOpCharSet: 2122c393a42Smrg FcCharSetDestroy (e->u.cval); 2132c393a42Smrg break; 214ca08ab68Smrg case FcOpLangSet: 215ca08ab68Smrg FcLangSetDestroy (e->u.lval); 216ca08ab68Smrg break; 2172c393a42Smrg case FcOpBool: 2182c393a42Smrg break; 2192c393a42Smrg case FcOpField: 2202c393a42Smrg break; 2212c393a42Smrg case FcOpConst: 222ca08ab68Smrg FcSharedStrFree (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 } 261a6844aabSmrg 262a6844aabSmrg e->op = FcOpNil; 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 2752c393a42Smrgtypedef enum _FcElement { 2762c393a42Smrg FcElementNone, 2772c393a42Smrg FcElementFontconfig, 2782c393a42Smrg FcElementDir, 2792c393a42Smrg FcElementCacheDir, 2802c393a42Smrg FcElementCache, 2812c393a42Smrg FcElementInclude, 2822c393a42Smrg FcElementConfig, 2832c393a42Smrg FcElementMatch, 2842c393a42Smrg FcElementAlias, 2852c393a42Smrg 2862c393a42Smrg FcElementBlank, 2872c393a42Smrg FcElementRescan, 2882c393a42Smrg 2892c393a42Smrg FcElementPrefer, 2902c393a42Smrg FcElementAccept, 2912c393a42Smrg FcElementDefault, 2922c393a42Smrg FcElementFamily, 2932c393a42Smrg 2942c393a42Smrg FcElementSelectfont, 2952c393a42Smrg FcElementAcceptfont, 2962c393a42Smrg FcElementRejectfont, 2972c393a42Smrg FcElementGlob, 2982c393a42Smrg FcElementPattern, 2992c393a42Smrg FcElementPatelt, 3002c393a42Smrg 3012c393a42Smrg FcElementTest, 3022c393a42Smrg FcElementEdit, 3032c393a42Smrg FcElementInt, 3042c393a42Smrg FcElementDouble, 3052c393a42Smrg FcElementString, 3062c393a42Smrg FcElementMatrix, 307ca08ab68Smrg FcElementRange, 3082c393a42Smrg FcElementBool, 309ca08ab68Smrg FcElementCharSet, 310ca08ab68Smrg FcElementLangSet, 3112c393a42Smrg FcElementName, 3122c393a42Smrg FcElementConst, 3132c393a42Smrg FcElementOr, 3142c393a42Smrg FcElementAnd, 3152c393a42Smrg FcElementEq, 3162c393a42Smrg FcElementNotEq, 3172c393a42Smrg FcElementLess, 3182c393a42Smrg FcElementLessEq, 3192c393a42Smrg FcElementMore, 3202c393a42Smrg FcElementMoreEq, 3212c393a42Smrg FcElementContains, 3222c393a42Smrg FcElementNotContains, 3232c393a42Smrg FcElementPlus, 3242c393a42Smrg FcElementMinus, 3252c393a42Smrg FcElementTimes, 3262c393a42Smrg FcElementDivide, 3272c393a42Smrg FcElementNot, 3282c393a42Smrg FcElementIf, 3292c393a42Smrg FcElementFloor, 3302c393a42Smrg FcElementCeil, 3312c393a42Smrg FcElementRound, 3322c393a42Smrg FcElementTrunc, 3332c393a42Smrg FcElementUnknown 3342c393a42Smrg} FcElement; 3352c393a42Smrg 3362c393a42Smrgstatic const struct { 3372c393a42Smrg const char name[16]; 3382c393a42Smrg FcElement element; 3392c393a42Smrg} fcElementMap[] = { 3402c393a42Smrg { "fontconfig", FcElementFontconfig }, 3412c393a42Smrg { "dir", FcElementDir }, 3422c393a42Smrg { "cachedir", FcElementCacheDir }, 3432c393a42Smrg { "cache", FcElementCache }, 3442c393a42Smrg { "include", FcElementInclude }, 3452c393a42Smrg { "config", FcElementConfig }, 3462c393a42Smrg { "match", FcElementMatch }, 3472c393a42Smrg { "alias", FcElementAlias }, 348ca08ab68Smrg 3492c393a42Smrg { "blank", FcElementBlank }, 3502c393a42Smrg { "rescan", FcElementRescan }, 3512c393a42Smrg 3522c393a42Smrg { "prefer", FcElementPrefer }, 3532c393a42Smrg { "accept", FcElementAccept }, 3542c393a42Smrg { "default", FcElementDefault }, 3552c393a42Smrg { "family", FcElementFamily }, 3562c393a42Smrg 3572c393a42Smrg { "selectfont", FcElementSelectfont }, 3582c393a42Smrg { "acceptfont", FcElementAcceptfont }, 3592c393a42Smrg { "rejectfont", FcElementRejectfont }, 3602c393a42Smrg { "glob", FcElementGlob }, 3612c393a42Smrg { "pattern", FcElementPattern }, 3622c393a42Smrg { "patelt", FcElementPatelt }, 3632c393a42Smrg 3642c393a42Smrg { "test", FcElementTest }, 3652c393a42Smrg { "edit", FcElementEdit }, 3662c393a42Smrg { "int", FcElementInt }, 3672c393a42Smrg { "double", FcElementDouble }, 3682c393a42Smrg { "string", FcElementString }, 3692c393a42Smrg { "matrix", FcElementMatrix }, 370ca08ab68Smrg { "range", FcElementRange }, 3712c393a42Smrg { "bool", FcElementBool }, 372ca08ab68Smrg { "charset", FcElementCharSet }, 373ca08ab68Smrg { "langset", FcElementLangSet }, 3742c393a42Smrg { "name", FcElementName }, 3752c393a42Smrg { "const", FcElementConst }, 3762c393a42Smrg { "or", FcElementOr }, 3772c393a42Smrg { "and", FcElementAnd }, 3782c393a42Smrg { "eq", FcElementEq }, 3792c393a42Smrg { "not_eq", FcElementNotEq }, 3802c393a42Smrg { "less", FcElementLess }, 3812c393a42Smrg { "less_eq", FcElementLessEq }, 3822c393a42Smrg { "more", FcElementMore }, 3832c393a42Smrg { "more_eq", FcElementMoreEq }, 3842c393a42Smrg { "contains", FcElementContains }, 3852c393a42Smrg { "not_contains", FcElementNotContains }, 3862c393a42Smrg { "plus", FcElementPlus }, 3872c393a42Smrg { "minus", FcElementMinus }, 3882c393a42Smrg { "times", FcElementTimes }, 3892c393a42Smrg { "divide", FcElementDivide }, 3902c393a42Smrg { "not", FcElementNot }, 3912c393a42Smrg { "if", FcElementIf }, 3922c393a42Smrg { "floor", FcElementFloor }, 3932c393a42Smrg { "ceil", FcElementCeil }, 3942c393a42Smrg { "round", FcElementRound }, 3952c393a42Smrg { "trunc", FcElementTrunc }, 3962c393a42Smrg}; 3972c393a42Smrg#define NUM_ELEMENT_MAPS (int) (sizeof fcElementMap / sizeof fcElementMap[0]) 3982c393a42Smrg 3992c393a42Smrgstatic FcElement 4002c393a42SmrgFcElementMap (const XML_Char *name) 4012c393a42Smrg{ 4022c393a42Smrg 4032c393a42Smrg int i; 4042c393a42Smrg for (i = 0; i < NUM_ELEMENT_MAPS; i++) 4052c393a42Smrg if (!strcmp ((char *) name, fcElementMap[i].name)) 4062c393a42Smrg return fcElementMap[i].element; 4072c393a42Smrg return FcElementUnknown; 4082c393a42Smrg} 4092c393a42Smrg 4102c393a42Smrgtypedef struct _FcPStack { 4112c393a42Smrg struct _FcPStack *prev; 4122c393a42Smrg FcElement element; 4132c393a42Smrg FcChar8 **attr; 4142c393a42Smrg FcStrBuf str; 415a6844aabSmrg FcChar8 *attr_buf_static[16]; 4162c393a42Smrg} FcPStack; 417ca08ab68Smrg 4182c393a42Smrgtypedef enum _FcVStackTag { 4192c393a42Smrg FcVStackNone, 4202c393a42Smrg 4212c393a42Smrg FcVStackString, 4222c393a42Smrg FcVStackFamily, 4232c393a42Smrg FcVStackField, 4242c393a42Smrg FcVStackConstant, 4252c393a42Smrg FcVStackGlob, 4262c393a42Smrg FcVStackPattern, 427ca08ab68Smrg 4282c393a42Smrg FcVStackPrefer, 4292c393a42Smrg FcVStackAccept, 4302c393a42Smrg FcVStackDefault, 431ca08ab68Smrg 4322c393a42Smrg FcVStackInteger, 4332c393a42Smrg FcVStackDouble, 4342c393a42Smrg FcVStackMatrix, 435ca08ab68Smrg FcVStackRange, 4362c393a42Smrg FcVStackBool, 437ca08ab68Smrg FcVStackCharSet, 438ca08ab68Smrg FcVStackLangSet, 439ca08ab68Smrg 4402c393a42Smrg FcVStackTest, 4412c393a42Smrg FcVStackExpr, 4422c393a42Smrg FcVStackEdit 4432c393a42Smrg} FcVStackTag; 4442c393a42Smrg 4452c393a42Smrgtypedef struct _FcVStack { 4462c393a42Smrg struct _FcVStack *prev; 4472c393a42Smrg FcPStack *pstack; /* related parse element */ 4482c393a42Smrg FcVStackTag tag; 4492c393a42Smrg union { 4502c393a42Smrg FcChar8 *string; 4512c393a42Smrg 4522c393a42Smrg int integer; 4532c393a42Smrg double _double; 4542c393a42Smrg FcMatrix *matrix; 455ca08ab68Smrg FcRange range; 456a6844aabSmrg FcBool bool_; 457ca08ab68Smrg FcCharSet *charset; 458ca08ab68Smrg FcLangSet *langset; 4592c393a42Smrg 4602c393a42Smrg FcTest *test; 4612c393a42Smrg FcQual qual; 4622c393a42Smrg FcOp op; 4632c393a42Smrg FcExpr *expr; 4642c393a42Smrg FcEdit *edit; 4652c393a42Smrg 4662c393a42Smrg FcPattern *pattern; 4672c393a42Smrg } u; 4682c393a42Smrg} FcVStack; 4692c393a42Smrg 4702c393a42Smrgtypedef struct _FcConfigParse { 4712c393a42Smrg FcPStack *pstack; 4722c393a42Smrg FcVStack *vstack; 4732c393a42Smrg FcBool error; 4742c393a42Smrg const FcChar8 *name; 4752c393a42Smrg FcConfig *config; 4762c393a42Smrg XML_Parser parser; 477a6844aabSmrg int pstack_static_used; 478a6844aabSmrg FcPStack pstack_static[8]; 479a6844aabSmrg int vstack_static_used; 480a6844aabSmrg FcVStack vstack_static[64]; 4812c393a42Smrg} FcConfigParse; 4822c393a42Smrg 4832c393a42Smrgtypedef enum _FcConfigSeverity { 4842c393a42Smrg FcSevereInfo, FcSevereWarning, FcSevereError 4852c393a42Smrg} FcConfigSeverity; 4862c393a42Smrg 4872c393a42Smrgstatic void 4882c393a42SmrgFcConfigMessage (FcConfigParse *parse, FcConfigSeverity severe, const char *fmt, ...) 4892c393a42Smrg{ 4902c393a42Smrg const char *s = "unknown"; 4912c393a42Smrg va_list args; 4922c393a42Smrg 4932c393a42Smrg va_start (args, fmt); 4942c393a42Smrg 4952c393a42Smrg switch (severe) { 4962c393a42Smrg case FcSevereInfo: s = "info"; break; 4972c393a42Smrg case FcSevereWarning: s = "warning"; break; 4982c393a42Smrg case FcSevereError: s = "error"; break; 4992c393a42Smrg } 5002c393a42Smrg if (parse) 5012c393a42Smrg { 5022c393a42Smrg if (parse->name) 5032c393a42Smrg fprintf (stderr, "Fontconfig %s: \"%s\", line %d: ", s, 5042c393a42Smrg parse->name, (int)XML_GetCurrentLineNumber (parse->parser)); 5052c393a42Smrg else 5062c393a42Smrg fprintf (stderr, "Fontconfig %s: line %d: ", s, 5072c393a42Smrg (int)XML_GetCurrentLineNumber (parse->parser)); 5082c393a42Smrg if (severe >= FcSevereError) 5092c393a42Smrg parse->error = FcTrue; 5102c393a42Smrg } 5112c393a42Smrg else 5122c393a42Smrg fprintf (stderr, "Fontconfig %s: ", s); 5132c393a42Smrg vfprintf (stderr, fmt, args); 5142c393a42Smrg fprintf (stderr, "\n"); 5152c393a42Smrg va_end (args); 5162c393a42Smrg} 5172c393a42Smrg 5182c393a42Smrg 5192c393a42Smrgstatic const char * 5202c393a42SmrgFcTypeName (FcType type) 5212c393a42Smrg{ 5222c393a42Smrg switch (type) { 5232c393a42Smrg case FcTypeVoid: 5242c393a42Smrg return "void"; 5252c393a42Smrg case FcTypeInteger: 5262c393a42Smrg case FcTypeDouble: 5272c393a42Smrg return "number"; 5282c393a42Smrg case FcTypeString: 5292c393a42Smrg return "string"; 5302c393a42Smrg case FcTypeBool: 5312c393a42Smrg return "bool"; 5322c393a42Smrg case FcTypeMatrix: 5332c393a42Smrg return "matrix"; 5342c393a42Smrg case FcTypeCharSet: 5352c393a42Smrg return "charset"; 5362c393a42Smrg case FcTypeFTFace: 5372c393a42Smrg return "FT_Face"; 5382c393a42Smrg case FcTypeLangSet: 5392c393a42Smrg return "langset"; 5402c393a42Smrg default: 5412c393a42Smrg return "unknown"; 5422c393a42Smrg } 5432c393a42Smrg} 5442c393a42Smrg 5452c393a42Smrgstatic void 5462c393a42SmrgFcTypecheckValue (FcConfigParse *parse, FcType value, FcType type) 5472c393a42Smrg{ 5482c393a42Smrg if (value == FcTypeInteger) 5492c393a42Smrg value = FcTypeDouble; 5502c393a42Smrg if (type == FcTypeInteger) 5512c393a42Smrg type = FcTypeDouble; 5522c393a42Smrg if (value != type) 5532c393a42Smrg { 5542c393a42Smrg if ((value == FcTypeLangSet && type == FcTypeString) || 5552c393a42Smrg (value == FcTypeString && type == FcTypeLangSet)) 5562c393a42Smrg return; 5572c393a42Smrg if (type == (FcType) -1) 5582c393a42Smrg return; 5592c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "saw %s, expected %s", 5602c393a42Smrg FcTypeName (value), FcTypeName (type)); 5612c393a42Smrg } 5622c393a42Smrg} 5632c393a42Smrg 5642c393a42Smrgstatic void 5652c393a42SmrgFcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type) 5662c393a42Smrg{ 5672c393a42Smrg const FcObjectType *o; 5682c393a42Smrg const FcConstant *c; 569ca08ab68Smrg 5702c393a42Smrg /* If parsing the expression failed, some nodes may be NULL */ 5712c393a42Smrg if (!expr) 5722c393a42Smrg return; 5732c393a42Smrg 574ca08ab68Smrg switch (FC_OP_GET_OP (expr->op)) { 5752c393a42Smrg case FcOpInteger: 5762c393a42Smrg case FcOpDouble: 5772c393a42Smrg FcTypecheckValue (parse, FcTypeDouble, type); 5782c393a42Smrg break; 5792c393a42Smrg case FcOpString: 5802c393a42Smrg FcTypecheckValue (parse, FcTypeString, type); 5812c393a42Smrg break; 5822c393a42Smrg case FcOpMatrix: 5832c393a42Smrg FcTypecheckValue (parse, FcTypeMatrix, type); 5842c393a42Smrg break; 5852c393a42Smrg case FcOpBool: 5862c393a42Smrg FcTypecheckValue (parse, FcTypeBool, type); 5872c393a42Smrg break; 5882c393a42Smrg case FcOpCharSet: 5892c393a42Smrg FcTypecheckValue (parse, FcTypeCharSet, type); 5902c393a42Smrg break; 591ca08ab68Smrg case FcOpLangSet: 592ca08ab68Smrg FcTypecheckValue (parse, FcTypeLangSet, type); 593ca08ab68Smrg break; 5942c393a42Smrg case FcOpNil: 5952c393a42Smrg break; 5962c393a42Smrg case FcOpField: 5972c393a42Smrg o = FcNameGetObjectType (FcObjectName (expr->u.object)); 5982c393a42Smrg if (o) 5992c393a42Smrg FcTypecheckValue (parse, o->type, type); 6002c393a42Smrg break; 6012c393a42Smrg case FcOpConst: 6022c393a42Smrg c = FcNameGetConstant (expr->u.constant); 6032c393a42Smrg if (c) 6042c393a42Smrg { 6052c393a42Smrg o = FcNameGetObjectType (c->object); 6062c393a42Smrg if (o) 6072c393a42Smrg FcTypecheckValue (parse, o->type, type); 6082c393a42Smrg } 609ca08ab68Smrg else 610ca08ab68Smrg FcConfigMessage (parse, FcSevereWarning, 6112c393a42Smrg "invalid constant used : %s", 6122c393a42Smrg expr->u.constant); 6132c393a42Smrg break; 6142c393a42Smrg case FcOpQuest: 6152c393a42Smrg FcTypecheckExpr (parse, expr->u.tree.left, FcTypeBool); 6162c393a42Smrg FcTypecheckExpr (parse, expr->u.tree.right->u.tree.left, type); 6172c393a42Smrg FcTypecheckExpr (parse, expr->u.tree.right->u.tree.right, type); 6182c393a42Smrg break; 6192c393a42Smrg case FcOpAssign: 6202c393a42Smrg case FcOpAssignReplace: 6212c393a42Smrg break; 6222c393a42Smrg case FcOpEqual: 6232c393a42Smrg case FcOpNotEqual: 6242c393a42Smrg case FcOpLess: 6252c393a42Smrg case FcOpLessEqual: 6262c393a42Smrg case FcOpMore: 6272c393a42Smrg case FcOpMoreEqual: 6282c393a42Smrg case FcOpContains: 6292c393a42Smrg case FcOpNotContains: 6302c393a42Smrg case FcOpListing: 6312c393a42Smrg FcTypecheckValue (parse, FcTypeBool, type); 6322c393a42Smrg break; 6332c393a42Smrg case FcOpComma: 6342c393a42Smrg case FcOpOr: 6352c393a42Smrg case FcOpAnd: 6362c393a42Smrg case FcOpPlus: 6372c393a42Smrg case FcOpMinus: 6382c393a42Smrg case FcOpTimes: 6392c393a42Smrg case FcOpDivide: 6402c393a42Smrg FcTypecheckExpr (parse, expr->u.tree.left, type); 6412c393a42Smrg FcTypecheckExpr (parse, expr->u.tree.right, type); 6422c393a42Smrg break; 6432c393a42Smrg case FcOpNot: 6442c393a42Smrg FcTypecheckValue (parse, FcTypeBool, type); 6452c393a42Smrg FcTypecheckExpr (parse, expr->u.tree.left, FcTypeBool); 6462c393a42Smrg break; 6472c393a42Smrg case FcOpFloor: 6482c393a42Smrg case FcOpCeil: 6492c393a42Smrg case FcOpRound: 6502c393a42Smrg case FcOpTrunc: 6512c393a42Smrg FcTypecheckValue (parse, FcTypeDouble, type); 6522c393a42Smrg FcTypecheckExpr (parse, expr->u.tree.left, FcTypeDouble); 6532c393a42Smrg break; 6542c393a42Smrg default: 6552c393a42Smrg break; 6562c393a42Smrg } 6572c393a42Smrg} 6582c393a42Smrg 6592c393a42Smrgstatic FcTest * 6602c393a42SmrgFcTestCreate (FcConfigParse *parse, 661ca08ab68Smrg FcMatchKind kind, 6622c393a42Smrg FcQual qual, 6632c393a42Smrg const FcChar8 *field, 6642c393a42Smrg FcOp compare, 6652c393a42Smrg FcExpr *expr) 6662c393a42Smrg{ 6672c393a42Smrg FcTest *test = (FcTest *) malloc (sizeof (FcTest)); 6682c393a42Smrg 6692c393a42Smrg if (test) 6702c393a42Smrg { 6712c393a42Smrg const FcObjectType *o; 6722c393a42Smrg 6732c393a42Smrg FcMemAlloc (FC_MEM_TEST, sizeof (FcTest)); 6742c393a42Smrg test->next = 0; 6752c393a42Smrg test->kind = kind; 6762c393a42Smrg test->qual = qual; 6772c393a42Smrg test->object = FcObjectFromName ((const char *) field); 6782c393a42Smrg test->op = compare; 6792c393a42Smrg test->expr = expr; 6802c393a42Smrg o = FcNameGetObjectType (FcObjectName (test->object)); 6812c393a42Smrg if (o) 6822c393a42Smrg FcTypecheckExpr (parse, expr, o->type); 6832c393a42Smrg } 6842c393a42Smrg return test; 6852c393a42Smrg} 6862c393a42Smrg 6872c393a42Smrgstatic FcEdit * 6882c393a42SmrgFcEditCreate (FcConfigParse *parse, 6892c393a42Smrg FcObject object, 6902c393a42Smrg FcOp op, 6912c393a42Smrg FcExpr *expr, 6922c393a42Smrg FcValueBinding binding) 6932c393a42Smrg{ 6942c393a42Smrg FcEdit *e = (FcEdit *) malloc (sizeof (FcEdit)); 6952c393a42Smrg 6962c393a42Smrg if (e) 6972c393a42Smrg { 6982c393a42Smrg const FcObjectType *o; 6992c393a42Smrg 7002c393a42Smrg e->next = 0; 7012c393a42Smrg e->object = object; 7022c393a42Smrg e->op = op; 7032c393a42Smrg e->expr = expr; 7042c393a42Smrg e->binding = binding; 7052c393a42Smrg o = FcNameGetObjectType (FcObjectName (e->object)); 7062c393a42Smrg if (o) 7072c393a42Smrg FcTypecheckExpr (parse, expr, o->type); 7082c393a42Smrg } 7092c393a42Smrg return e; 7102c393a42Smrg} 7112c393a42Smrg 7122c393a42Smrgstatic FcVStack * 713a6844aabSmrgFcVStackCreateAndPush (FcConfigParse *parse) 7142c393a42Smrg{ 7152c393a42Smrg FcVStack *new; 7162c393a42Smrg 717a6844aabSmrg if (parse->vstack_static_used < sizeof (parse->vstack_static) / sizeof (parse->vstack_static[0])) 718a6844aabSmrg new = &parse->vstack_static[parse->vstack_static_used++]; 719a6844aabSmrg else 720a6844aabSmrg { 721a6844aabSmrg new = malloc (sizeof (FcVStack)); 722a6844aabSmrg if (!new) 723a6844aabSmrg return 0; 724a6844aabSmrg FcMemAlloc (FC_MEM_VSTACK, sizeof (FcVStack)); 725a6844aabSmrg } 7262c393a42Smrg new->tag = FcVStackNone; 7272c393a42Smrg new->prev = 0; 7282c393a42Smrg 729a6844aabSmrg new->prev = parse->vstack; 730a6844aabSmrg new->pstack = parse->pstack ? parse->pstack->prev : 0; 731a6844aabSmrg parse->vstack = new; 7322c393a42Smrg 733a6844aabSmrg return new; 7342c393a42Smrg} 7352c393a42Smrg 7362c393a42Smrgstatic FcBool 7372c393a42SmrgFcVStackPushString (FcConfigParse *parse, FcVStackTag tag, FcChar8 *string) 7382c393a42Smrg{ 739a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 7402c393a42Smrg if (!vstack) 7412c393a42Smrg return FcFalse; 7422c393a42Smrg vstack->u.string = string; 7432c393a42Smrg vstack->tag = tag; 7442c393a42Smrg return FcTrue; 7452c393a42Smrg} 7462c393a42Smrg 7472c393a42Smrgstatic FcBool 7482c393a42SmrgFcVStackPushInteger (FcConfigParse *parse, int integer) 7492c393a42Smrg{ 750a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 7512c393a42Smrg if (!vstack) 7522c393a42Smrg return FcFalse; 7532c393a42Smrg vstack->u.integer = integer; 7542c393a42Smrg vstack->tag = FcVStackInteger; 7552c393a42Smrg return FcTrue; 7562c393a42Smrg} 7572c393a42Smrg 7582c393a42Smrgstatic FcBool 7592c393a42SmrgFcVStackPushDouble (FcConfigParse *parse, double _double) 7602c393a42Smrg{ 761a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 7622c393a42Smrg if (!vstack) 7632c393a42Smrg return FcFalse; 7642c393a42Smrg vstack->u._double = _double; 7652c393a42Smrg vstack->tag = FcVStackDouble; 7662c393a42Smrg return FcTrue; 7672c393a42Smrg} 7682c393a42Smrg 7692c393a42Smrgstatic FcBool 7702c393a42SmrgFcVStackPushMatrix (FcConfigParse *parse, FcMatrix *matrix) 7712c393a42Smrg{ 772a6844aabSmrg FcVStack *vstack; 7732c393a42Smrg matrix = FcMatrixCopy (matrix); 7742c393a42Smrg if (!matrix) 7752c393a42Smrg return FcFalse; 776a6844aabSmrg vstack = FcVStackCreateAndPush (parse); 777a6844aabSmrg if (!vstack) 778a6844aabSmrg return FcFalse; 7792c393a42Smrg vstack->u.matrix = matrix; 7802c393a42Smrg vstack->tag = FcVStackMatrix; 7812c393a42Smrg return FcTrue; 7822c393a42Smrg} 7832c393a42Smrg 784ca08ab68Smrgstatic FcBool 785ca08ab68SmrgFcVStackPushRange (FcConfigParse *parse, FcRange *range) 786ca08ab68Smrg{ 787ca08ab68Smrg FcVStack *vstack = FcVStackCreateAndPush (parse); 788ca08ab68Smrg if (!vstack) 789ca08ab68Smrg return FcFalse; 790ca08ab68Smrg vstack->u.range.begin = range->begin; 791ca08ab68Smrg vstack->u.range.end = range->end; 792ca08ab68Smrg vstack->tag = FcVStackRange; 793ca08ab68Smrg return FcTrue; 794ca08ab68Smrg} 795ca08ab68Smrg 7962c393a42Smrgstatic FcBool 797a6844aabSmrgFcVStackPushBool (FcConfigParse *parse, FcBool bool_) 7982c393a42Smrg{ 799a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 8002c393a42Smrg if (!vstack) 8012c393a42Smrg return FcFalse; 802a6844aabSmrg vstack->u.bool_ = bool_; 8032c393a42Smrg vstack->tag = FcVStackBool; 8042c393a42Smrg return FcTrue; 8052c393a42Smrg} 8062c393a42Smrg 807ca08ab68Smrgstatic FcBool 808ca08ab68SmrgFcVStackPushCharSet (FcConfigParse *parse, FcCharSet *charset) 809ca08ab68Smrg{ 810ca08ab68Smrg FcVStack *vstack; 811ca08ab68Smrg if (!charset) 812ca08ab68Smrg return FcFalse; 813ca08ab68Smrg vstack = FcVStackCreateAndPush (parse); 814ca08ab68Smrg if (!vstack) 815ca08ab68Smrg return FcFalse; 816ca08ab68Smrg vstack->u.charset = charset; 817ca08ab68Smrg vstack->tag = FcVStackCharSet; 818ca08ab68Smrg return FcTrue; 819ca08ab68Smrg} 820ca08ab68Smrg 821ca08ab68Smrgstatic FcBool 822ca08ab68SmrgFcVStackPushLangSet (FcConfigParse *parse, FcLangSet *langset) 823ca08ab68Smrg{ 824ca08ab68Smrg FcVStack *vstack; 825ca08ab68Smrg if (!langset) 826ca08ab68Smrg return FcFalse; 827ca08ab68Smrg vstack = FcVStackCreateAndPush (parse); 828ca08ab68Smrg if (!vstack) 829ca08ab68Smrg return FcFalse; 830ca08ab68Smrg vstack->u.langset = langset; 831ca08ab68Smrg vstack->tag = FcVStackLangSet; 832ca08ab68Smrg return FcTrue; 833ca08ab68Smrg} 834ca08ab68Smrg 8352c393a42Smrgstatic FcBool 8362c393a42SmrgFcVStackPushTest (FcConfigParse *parse, FcTest *test) 8372c393a42Smrg{ 838a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 8392c393a42Smrg if (!vstack) 8402c393a42Smrg return FcFalse; 8412c393a42Smrg vstack->u.test = test; 8422c393a42Smrg vstack->tag = FcVStackTest; 8432c393a42Smrg return FcTrue; 8442c393a42Smrg} 8452c393a42Smrg 8462c393a42Smrgstatic FcBool 8472c393a42SmrgFcVStackPushExpr (FcConfigParse *parse, FcVStackTag tag, FcExpr *expr) 8482c393a42Smrg{ 849a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 8502c393a42Smrg if (!vstack) 8512c393a42Smrg return FcFalse; 8522c393a42Smrg vstack->u.expr = expr; 8532c393a42Smrg vstack->tag = tag; 8542c393a42Smrg return FcTrue; 8552c393a42Smrg} 8562c393a42Smrg 8572c393a42Smrgstatic FcBool 8582c393a42SmrgFcVStackPushEdit (FcConfigParse *parse, FcEdit *edit) 8592c393a42Smrg{ 860a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 8612c393a42Smrg if (!vstack) 8622c393a42Smrg return FcFalse; 8632c393a42Smrg vstack->u.edit = edit; 8642c393a42Smrg vstack->tag = FcVStackEdit; 8652c393a42Smrg return FcTrue; 8662c393a42Smrg} 8672c393a42Smrg 8682c393a42Smrgstatic FcBool 8692c393a42SmrgFcVStackPushPattern (FcConfigParse *parse, FcPattern *pattern) 8702c393a42Smrg{ 871a6844aabSmrg FcVStack *vstack = FcVStackCreateAndPush (parse); 8722c393a42Smrg if (!vstack) 8732c393a42Smrg return FcFalse; 8742c393a42Smrg vstack->u.pattern = pattern; 8752c393a42Smrg vstack->tag = FcVStackPattern; 8762c393a42Smrg return FcTrue; 8772c393a42Smrg} 8782c393a42Smrg 8792c393a42Smrgstatic FcVStack * 8802c393a42SmrgFcVStackFetch (FcConfigParse *parse, int off) 8812c393a42Smrg{ 8822c393a42Smrg FcVStack *vstack; 8832c393a42Smrg 8842c393a42Smrg for (vstack = parse->vstack; vstack && off-- > 0; vstack = vstack->prev); 8852c393a42Smrg return vstack; 8862c393a42Smrg} 8872c393a42Smrg 888a6844aabSmrgstatic FcVStack * 889a6844aabSmrgFcVStackPeek (FcConfigParse *parse) 8902c393a42Smrg{ 891a6844aabSmrg FcVStack *vstack = parse->vstack; 892a6844aabSmrg 893a6844aabSmrg return vstack && vstack->pstack == parse->pstack ? vstack : 0; 8942c393a42Smrg} 8952c393a42Smrg 896a6844aabSmrgstatic void 897a6844aabSmrgFcVStackPopAndDestroy (FcConfigParse *parse) 8982c393a42Smrg{ 8992c393a42Smrg FcVStack *vstack = parse->vstack; 900ca08ab68Smrg 9012c393a42Smrg if (!vstack || vstack->pstack != parse->pstack) 902a6844aabSmrg return; 903a6844aabSmrg 9042c393a42Smrg parse->vstack = vstack->prev; 905a6844aabSmrg 906a6844aabSmrg switch (vstack->tag) { 907a6844aabSmrg case FcVStackNone: 908a6844aabSmrg break; 909a6844aabSmrg case FcVStackFamily: 910a6844aabSmrg break; 911a6844aabSmrg case FcVStackString: 912a6844aabSmrg case FcVStackField: 913a6844aabSmrg case FcVStackConstant: 914a6844aabSmrg case FcVStackGlob: 915a6844aabSmrg FcStrFree (vstack->u.string); 916a6844aabSmrg break; 917a6844aabSmrg case FcVStackPattern: 918a6844aabSmrg FcPatternDestroy (vstack->u.pattern); 919a6844aabSmrg break; 920a6844aabSmrg case FcVStackInteger: 921a6844aabSmrg case FcVStackDouble: 922a6844aabSmrg break; 923a6844aabSmrg case FcVStackMatrix: 924a6844aabSmrg FcMatrixFree (vstack->u.matrix); 925a6844aabSmrg break; 926ca08ab68Smrg case FcVStackRange: 927a6844aabSmrg case FcVStackBool: 928a6844aabSmrg break; 929ca08ab68Smrg case FcVStackCharSet: 930ca08ab68Smrg FcCharSetDestroy (vstack->u.charset); 931ca08ab68Smrg break; 932ca08ab68Smrg case FcVStackLangSet: 933ca08ab68Smrg FcLangSetDestroy (vstack->u.langset); 934ca08ab68Smrg break; 935a6844aabSmrg case FcVStackTest: 936a6844aabSmrg FcTestDestroy (vstack->u.test); 937a6844aabSmrg break; 938a6844aabSmrg case FcVStackExpr: 939a6844aabSmrg case FcVStackPrefer: 940a6844aabSmrg case FcVStackAccept: 941a6844aabSmrg case FcVStackDefault: 942a6844aabSmrg FcExprDestroy (vstack->u.expr); 943a6844aabSmrg break; 944a6844aabSmrg case FcVStackEdit: 945a6844aabSmrg FcEditDestroy (vstack->u.edit); 946a6844aabSmrg break; 947a6844aabSmrg } 948a6844aabSmrg 949a6844aabSmrg if (vstack == &parse->vstack_static[parse->vstack_static_used - 1]) 950a6844aabSmrg parse->vstack_static_used--; 951a6844aabSmrg else 952a6844aabSmrg { 953a6844aabSmrg FcMemFree (FC_MEM_VSTACK, sizeof (FcVStack)); 954a6844aabSmrg free (vstack); 955a6844aabSmrg } 956a6844aabSmrg} 957a6844aabSmrg 958a6844aabSmrgstatic void 959a6844aabSmrgFcVStackClear (FcConfigParse *parse) 960a6844aabSmrg{ 961a6844aabSmrg while (FcVStackPeek (parse)) 962a6844aabSmrg FcVStackPopAndDestroy (parse); 9632c393a42Smrg} 9642c393a42Smrg 9652c393a42Smrgstatic int 9662c393a42SmrgFcVStackElements (FcConfigParse *parse) 9672c393a42Smrg{ 9682c393a42Smrg int h = 0; 9692c393a42Smrg FcVStack *vstack = parse->vstack; 9702c393a42Smrg while (vstack && vstack->pstack == parse->pstack) 9712c393a42Smrg { 9722c393a42Smrg h++; 9732c393a42Smrg vstack = vstack->prev; 9742c393a42Smrg } 9752c393a42Smrg return h; 9762c393a42Smrg} 9772c393a42Smrg 9782c393a42Smrgstatic FcChar8 ** 979a6844aabSmrgFcConfigSaveAttr (const XML_Char **attr, FcChar8 **buf, int size_bytes) 9802c393a42Smrg{ 9812c393a42Smrg int slen; 9822c393a42Smrg int i; 9832c393a42Smrg FcChar8 **new; 9842c393a42Smrg FcChar8 *s; 9852c393a42Smrg 9862c393a42Smrg if (!attr) 9872c393a42Smrg return 0; 9882c393a42Smrg slen = 0; 9892c393a42Smrg for (i = 0; attr[i]; i++) 9902c393a42Smrg slen += strlen ((char *) attr[i]) + 1; 991a6844aabSmrg if (i == 0) 9922c393a42Smrg return 0; 993a6844aabSmrg slen += (i + 1) * sizeof (FcChar8 *); 994a6844aabSmrg if (slen <= size_bytes) 995a6844aabSmrg new = buf; 996a6844aabSmrg else 997a6844aabSmrg { 998a6844aabSmrg new = malloc (slen); 999a6844aabSmrg if (!new) 1000a6844aabSmrg { 1001a6844aabSmrg FcConfigMessage (0, FcSevereError, "out of memory"); 1002a6844aabSmrg return 0; 1003a6844aabSmrg } 1004a6844aabSmrg FcMemAlloc (FC_MEM_ATTR, 1); /* size is too expensive */ 1005a6844aabSmrg } 10062c393a42Smrg s = (FcChar8 *) (new + (i + 1)); 10072c393a42Smrg for (i = 0; attr[i]; i++) 10082c393a42Smrg { 10092c393a42Smrg new[i] = s; 10102c393a42Smrg strcpy ((char *) s, (char *) attr[i]); 10112c393a42Smrg s += strlen ((char *) s) + 1; 10122c393a42Smrg } 10132c393a42Smrg new[i] = 0; 10142c393a42Smrg return new; 10152c393a42Smrg} 10162c393a42Smrg 10172c393a42Smrgstatic FcBool 10182c393a42SmrgFcPStackPush (FcConfigParse *parse, FcElement element, const XML_Char **attr) 10192c393a42Smrg{ 1020a6844aabSmrg FcPStack *new; 10212c393a42Smrg 1022a6844aabSmrg if (parse->pstack_static_used < sizeof (parse->pstack_static) / sizeof (parse->pstack_static[0])) 1023a6844aabSmrg new = &parse->pstack_static[parse->pstack_static_used++]; 1024a6844aabSmrg else 10252c393a42Smrg { 1026a6844aabSmrg new = malloc (sizeof (FcPStack)); 1027a6844aabSmrg if (!new) 10282c393a42Smrg return FcFalse; 1029a6844aabSmrg FcMemAlloc (FC_MEM_PSTACK, sizeof (FcPStack)); 10302c393a42Smrg } 1031a6844aabSmrg 1032a6844aabSmrg new->prev = parse->pstack; 1033a6844aabSmrg new->element = element; 1034a6844aabSmrg new->attr = FcConfigSaveAttr (attr, new->attr_buf_static, sizeof (new->attr_buf_static)); 10352c393a42Smrg FcStrBufInit (&new->str, 0, 0); 10362c393a42Smrg parse->pstack = new; 10372c393a42Smrg return FcTrue; 10382c393a42Smrg} 10392c393a42Smrg 10402c393a42Smrgstatic FcBool 10412c393a42SmrgFcPStackPop (FcConfigParse *parse) 10422c393a42Smrg{ 10432c393a42Smrg FcPStack *old; 1044ca08ab68Smrg 1045ca08ab68Smrg if (!parse->pstack) 10462c393a42Smrg { 10472c393a42Smrg FcConfigMessage (parse, FcSevereError, "mismatching element"); 10482c393a42Smrg return FcFalse; 10492c393a42Smrg } 10502c393a42Smrg FcVStackClear (parse); 10512c393a42Smrg old = parse->pstack; 10522c393a42Smrg parse->pstack = old->prev; 10532c393a42Smrg FcStrBufDestroy (&old->str); 1054a6844aabSmrg if (old->attr && old->attr != old->attr_buf_static) 10552c393a42Smrg { 10562c393a42Smrg FcMemFree (FC_MEM_ATTR, 1); /* size is to expensive */ 10572c393a42Smrg free (old->attr); 10582c393a42Smrg } 1059a6844aabSmrg 1060a6844aabSmrg if (old == &parse->pstack_static[parse->pstack_static_used - 1]) 1061a6844aabSmrg parse->pstack_static_used--; 1062a6844aabSmrg else 1063a6844aabSmrg { 1064a6844aabSmrg FcMemFree (FC_MEM_PSTACK, sizeof (FcPStack)); 1065a6844aabSmrg free (old); 1066a6844aabSmrg } 10672c393a42Smrg return FcTrue; 10682c393a42Smrg} 10692c393a42Smrg 10702c393a42Smrgstatic FcBool 10712c393a42SmrgFcConfigInit (FcConfigParse *parse, const FcChar8 *name, FcConfig *config, XML_Parser parser) 10722c393a42Smrg{ 10732c393a42Smrg parse->pstack = 0; 1074a6844aabSmrg parse->pstack_static_used = 0; 10752c393a42Smrg parse->vstack = 0; 1076a6844aabSmrg parse->vstack_static_used = 0; 10772c393a42Smrg parse->error = FcFalse; 10782c393a42Smrg parse->name = name; 10792c393a42Smrg parse->config = config; 10802c393a42Smrg parse->parser = parser; 10812c393a42Smrg return FcTrue; 10822c393a42Smrg} 10832c393a42Smrg 10842c393a42Smrgstatic void 10852c393a42SmrgFcConfigCleanup (FcConfigParse *parse) 10862c393a42Smrg{ 10872c393a42Smrg while (parse->pstack) 10882c393a42Smrg FcPStackPop (parse); 10892c393a42Smrg} 10902c393a42Smrg 10912c393a42Smrgstatic const FcChar8 * 10922c393a42SmrgFcConfigGetAttribute (FcConfigParse *parse, const char *attr) 10932c393a42Smrg{ 10942c393a42Smrg FcChar8 **attrs; 10952c393a42Smrg if (!parse->pstack) 10962c393a42Smrg return 0; 10972c393a42Smrg 10982c393a42Smrg attrs = parse->pstack->attr; 10992c393a42Smrg if (!attrs) 11002c393a42Smrg return 0; 11012c393a42Smrg 11022c393a42Smrg while (*attrs) 11032c393a42Smrg { 11042c393a42Smrg if (!strcmp ((char *) *attrs, attr)) 11052c393a42Smrg return attrs[1]; 11062c393a42Smrg attrs += 2; 11072c393a42Smrg } 11082c393a42Smrg return 0; 11092c393a42Smrg} 11102c393a42Smrg 11112c393a42Smrgstatic void 11122c393a42SmrgFcStartElement(void *userData, const XML_Char *name, const XML_Char **attr) 11132c393a42Smrg{ 11142c393a42Smrg FcConfigParse *parse = userData; 11152c393a42Smrg FcElement element; 1116ca08ab68Smrg 11172c393a42Smrg element = FcElementMap (name); 11182c393a42Smrg if (element == FcElementUnknown) 11192c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "unknown element \"%s\"", name); 1120ca08ab68Smrg 11212c393a42Smrg if (!FcPStackPush (parse, element, attr)) 11222c393a42Smrg { 11232c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 11242c393a42Smrg return; 11252c393a42Smrg } 11262c393a42Smrg return; 11272c393a42Smrg} 11282c393a42Smrg 11292c393a42Smrgstatic void 11302c393a42SmrgFcParseBlank (FcConfigParse *parse) 11312c393a42Smrg{ 1132ca08ab68Smrg int n = FcVStackElements (parse); 1133ca08ab68Smrg FcChar32 i; 11342c393a42Smrg while (n-- > 0) 11352c393a42Smrg { 11362c393a42Smrg FcVStack *v = FcVStackFetch (parse, n); 1137ca08ab68Smrg if (!parse->config->blanks) 11382c393a42Smrg { 1139ca08ab68Smrg parse->config->blanks = FcBlanksCreate (); 11402c393a42Smrg if (!parse->config->blanks) 1141ca08ab68Smrg goto bail; 1142ca08ab68Smrg } 1143ca08ab68Smrg switch (v->tag) { 1144ca08ab68Smrg case FcVStackInteger: 11452c393a42Smrg if (!FcBlanksAdd (parse->config->blanks, v->u.integer)) 1146ca08ab68Smrg goto bail; 1147ca08ab68Smrg break; 1148ca08ab68Smrg case FcVStackRange: 1149ca08ab68Smrg if (v->u.range.begin <= v->u.range.end) 11502c393a42Smrg { 1151ca08ab68Smrg for (i = v->u.range.begin; i <= v->u.range.end; i++) 1152ca08ab68Smrg { 1153ca08ab68Smrg if (!FcBlanksAdd (parse->config->blanks, i)) 1154ca08ab68Smrg goto bail; 1155ca08ab68Smrg } 11562c393a42Smrg } 1157ca08ab68Smrg break; 1158ca08ab68Smrg default: 1159ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "invalid element in blank"); 1160ca08ab68Smrg break; 11612c393a42Smrg } 11622c393a42Smrg } 1163ca08ab68Smrg return; 1164ca08ab68Smrg bail: 1165ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 11662c393a42Smrg} 11672c393a42Smrg 11682c393a42Smrgstatic void 11692c393a42SmrgFcParseRescan (FcConfigParse *parse) 11702c393a42Smrg{ 11712c393a42Smrg int n = FcVStackElements (parse); 11722c393a42Smrg while (n-- > 0) 11732c393a42Smrg { 11742c393a42Smrg FcVStack *v = FcVStackFetch (parse, n); 11752c393a42Smrg if (v->tag != FcVStackInteger) 11762c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "non-integer rescan"); 11772c393a42Smrg else 11782c393a42Smrg parse->config->rescanInterval = v->u.integer; 11792c393a42Smrg } 11802c393a42Smrg} 11812c393a42Smrg 11822c393a42Smrgstatic void 11832c393a42SmrgFcParseInt (FcConfigParse *parse) 11842c393a42Smrg{ 11852c393a42Smrg FcChar8 *s, *end; 11862c393a42Smrg int l; 1187ca08ab68Smrg 11882c393a42Smrg if (!parse->pstack) 11892c393a42Smrg return; 1190a6844aabSmrg s = FcStrBufDoneStatic (&parse->pstack->str); 11912c393a42Smrg if (!s) 11922c393a42Smrg { 11932c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 11942c393a42Smrg return; 11952c393a42Smrg } 11962c393a42Smrg end = 0; 11972c393a42Smrg l = (int) strtol ((char *) s, (char **)&end, 0); 11982c393a42Smrg if (end != s + strlen ((char *) s)) 11992c393a42Smrg FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid integer", s); 12002c393a42Smrg else 12012c393a42Smrg FcVStackPushInteger (parse, l); 1202a6844aabSmrg FcStrBufDestroy (&parse->pstack->str); 12032c393a42Smrg} 12042c393a42Smrg 12052c393a42Smrg/* 1206ca08ab68Smrg * idea copied from glib g_ascii_strtod with 1207ca08ab68Smrg * permission of the author (Alexander Larsson) 12082c393a42Smrg */ 12092c393a42Smrg 12102c393a42Smrg#include <locale.h> 12112c393a42Smrg 1212ca08ab68Smrgstatic double 12132c393a42SmrgFcStrtod (char *s, char **end) 12142c393a42Smrg{ 12152c393a42Smrg struct lconv *locale_data; 12162c393a42Smrg char *dot; 12172c393a42Smrg double v; 12182c393a42Smrg 12192c393a42Smrg /* 12202c393a42Smrg * Have to swap the decimal point to match the current locale 12212c393a42Smrg * if that locale doesn't use 0x2e 12222c393a42Smrg */ 12232c393a42Smrg if ((dot = strchr (s, 0x2e)) && 12242c393a42Smrg (locale_data = localeconv ()) && 12252c393a42Smrg (locale_data->decimal_point[0] != 0x2e || 12262c393a42Smrg locale_data->decimal_point[1] != 0)) 12272c393a42Smrg { 12282c393a42Smrg char buf[128]; 12292c393a42Smrg int slen = strlen (s); 12302c393a42Smrg int dlen = strlen (locale_data->decimal_point); 12312c393a42Smrg 12322c393a42Smrg if (slen + dlen > (int) sizeof (buf)) 12332c393a42Smrg { 12342c393a42Smrg if (end) 12352c393a42Smrg *end = s; 12362c393a42Smrg v = 0; 12372c393a42Smrg } 12382c393a42Smrg else 12392c393a42Smrg { 12402c393a42Smrg char *buf_end; 12412c393a42Smrg /* mantissa */ 12422c393a42Smrg strncpy (buf, s, dot - s); 12432c393a42Smrg /* decimal point */ 12442c393a42Smrg strcpy (buf + (dot - s), locale_data->decimal_point); 12452c393a42Smrg /* rest of number */ 12462c393a42Smrg strcpy (buf + (dot - s) + dlen, dot + 1); 12472c393a42Smrg buf_end = 0; 12482c393a42Smrg v = strtod (buf, &buf_end); 12492c393a42Smrg if (buf_end) { 12502c393a42Smrg buf_end = s + (buf_end - buf); 12512c393a42Smrg if (buf_end > dot) 12522c393a42Smrg buf_end -= dlen - 1; 12532c393a42Smrg } 12542c393a42Smrg if (end) 12552c393a42Smrg *end = buf_end; 12562c393a42Smrg } 12572c393a42Smrg } 12582c393a42Smrg else 12592c393a42Smrg v = strtod (s, end); 12602c393a42Smrg return v; 12612c393a42Smrg} 12622c393a42Smrg 12632c393a42Smrgstatic void 12642c393a42SmrgFcParseDouble (FcConfigParse *parse) 12652c393a42Smrg{ 12662c393a42Smrg FcChar8 *s, *end; 12672c393a42Smrg double d; 1268ca08ab68Smrg 12692c393a42Smrg if (!parse->pstack) 12702c393a42Smrg return; 1271a6844aabSmrg s = FcStrBufDoneStatic (&parse->pstack->str); 12722c393a42Smrg if (!s) 12732c393a42Smrg { 12742c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 12752c393a42Smrg return; 12762c393a42Smrg } 12772c393a42Smrg end = 0; 12782c393a42Smrg d = FcStrtod ((char *) s, (char **)&end); 12792c393a42Smrg if (end != s + strlen ((char *) s)) 12802c393a42Smrg FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid double", s); 12812c393a42Smrg else 12822c393a42Smrg FcVStackPushDouble (parse, d); 1283a6844aabSmrg FcStrBufDestroy (&parse->pstack->str); 12842c393a42Smrg} 12852c393a42Smrg 12862c393a42Smrgstatic void 12872c393a42SmrgFcParseString (FcConfigParse *parse, FcVStackTag tag) 12882c393a42Smrg{ 12892c393a42Smrg FcChar8 *s; 1290ca08ab68Smrg 12912c393a42Smrg if (!parse->pstack) 12922c393a42Smrg return; 12932c393a42Smrg s = FcStrBufDone (&parse->pstack->str); 12942c393a42Smrg if (!s) 12952c393a42Smrg { 12962c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 12972c393a42Smrg return; 12982c393a42Smrg } 12992c393a42Smrg if (!FcVStackPushString (parse, tag, s)) 13002c393a42Smrg FcStrFree (s); 13012c393a42Smrg} 13022c393a42Smrg 13032c393a42Smrgstatic void 13042c393a42SmrgFcParseMatrix (FcConfigParse *parse) 13052c393a42Smrg{ 13062c393a42Smrg FcVStack *vstack; 13072c393a42Smrg enum { m_done, m_xx, m_xy, m_yx, m_yy } matrix_state = m_yy; 13082c393a42Smrg FcMatrix m; 1309ca08ab68Smrg 1310a6844aabSmrg while ((vstack = FcVStackPeek (parse))) 13112c393a42Smrg { 13122c393a42Smrg double v; 13132c393a42Smrg switch (vstack->tag) { 13142c393a42Smrg case FcVStackInteger: 13152c393a42Smrg v = vstack->u.integer; 13162c393a42Smrg break; 13172c393a42Smrg case FcVStackDouble: 13182c393a42Smrg v = vstack->u._double; 13192c393a42Smrg break; 13202c393a42Smrg default: 13212c393a42Smrg FcConfigMessage (parse, FcSevereError, "non-double matrix element"); 13222c393a42Smrg v = 1.0; 13232c393a42Smrg break; 13242c393a42Smrg } 13252c393a42Smrg switch (matrix_state) { 13262c393a42Smrg case m_xx: m.xx = v; break; 13272c393a42Smrg case m_xy: m.xy = v; break; 13282c393a42Smrg case m_yx: m.yx = v; break; 13292c393a42Smrg case m_yy: m.yy = v; break; 13302c393a42Smrg default: break; 13312c393a42Smrg } 1332a6844aabSmrg FcVStackPopAndDestroy (parse); 13332c393a42Smrg matrix_state--; 13342c393a42Smrg } 13352c393a42Smrg if (matrix_state != m_done) 13362c393a42Smrg FcConfigMessage (parse, FcSevereError, "wrong number of matrix elements"); 13372c393a42Smrg else 13382c393a42Smrg FcVStackPushMatrix (parse, &m); 13392c393a42Smrg} 13402c393a42Smrg 1341ca08ab68Smrgstatic void 1342ca08ab68SmrgFcParseRange (FcConfigParse *parse) 1343ca08ab68Smrg{ 1344ca08ab68Smrg FcVStack *vstack; 1345ca08ab68Smrg FcRange r; 1346ca08ab68Smrg FcChar32 n; 1347ca08ab68Smrg int count = 1; 1348ca08ab68Smrg 1349ca08ab68Smrg while ((vstack = FcVStackPeek (parse))) 1350ca08ab68Smrg { 1351ca08ab68Smrg if (count < 0) 1352ca08ab68Smrg { 1353ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "too many elements in range"); 1354ca08ab68Smrg return; 1355ca08ab68Smrg } 1356ca08ab68Smrg switch (vstack->tag) { 1357ca08ab68Smrg case FcVStackInteger: 1358ca08ab68Smrg n = vstack->u.integer; 1359ca08ab68Smrg break; 1360ca08ab68Smrg default: 1361ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "invalid element in range"); 1362ca08ab68Smrg n = 0; 1363ca08ab68Smrg break; 1364ca08ab68Smrg } 1365ca08ab68Smrg if (count == 1) 1366ca08ab68Smrg r.end = n; 1367ca08ab68Smrg else 1368ca08ab68Smrg r.begin = n; 1369ca08ab68Smrg count--; 1370ca08ab68Smrg FcVStackPopAndDestroy (parse); 1371ca08ab68Smrg } 1372ca08ab68Smrg if (count < 0) 1373ca08ab68Smrg { 1374ca08ab68Smrg if (r.begin > r.end) 1375ca08ab68Smrg { 1376ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "invalid range"); 1377ca08ab68Smrg return; 1378ca08ab68Smrg } 1379ca08ab68Smrg FcVStackPushRange (parse, &r); 1380ca08ab68Smrg } 1381ca08ab68Smrg else 1382ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "invalid range"); 1383ca08ab68Smrg} 1384ca08ab68Smrg 13852c393a42Smrgstatic FcBool 1386a6844aabSmrgFcConfigLexBool (FcConfigParse *parse, const FcChar8 *bool_) 13872c393a42Smrg{ 13882c393a42Smrg FcBool result = FcFalse; 13892c393a42Smrg 1390a6844aabSmrg if (!FcNameBool (bool_, &result)) 13912c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "\"%s\" is not known boolean", 1392a6844aabSmrg bool_); 13932c393a42Smrg return result; 13942c393a42Smrg} 13952c393a42Smrg 13962c393a42Smrgstatic void 13972c393a42SmrgFcParseBool (FcConfigParse *parse) 13982c393a42Smrg{ 13992c393a42Smrg FcChar8 *s; 14002c393a42Smrg 14012c393a42Smrg if (!parse->pstack) 14022c393a42Smrg return; 1403a6844aabSmrg s = FcStrBufDoneStatic (&parse->pstack->str); 14042c393a42Smrg if (!s) 14052c393a42Smrg { 14062c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 14072c393a42Smrg return; 14082c393a42Smrg } 14092c393a42Smrg FcVStackPushBool (parse, FcConfigLexBool (parse, s)); 1410a6844aabSmrg FcStrBufDestroy (&parse->pstack->str); 14112c393a42Smrg} 14122c393a42Smrg 1413ca08ab68Smrgstatic void 1414ca08ab68SmrgFcParseCharSet (FcConfigParse *parse) 1415ca08ab68Smrg{ 1416ca08ab68Smrg FcVStack *vstack; 1417ca08ab68Smrg FcCharSet *charset = FcCharSetCreate (); 1418ca08ab68Smrg FcChar32 i; 1419ca08ab68Smrg int n = 0; 1420ca08ab68Smrg 1421ca08ab68Smrg while ((vstack = FcVStackPeek (parse))) 1422ca08ab68Smrg { 1423ca08ab68Smrg switch (vstack->tag) { 1424ca08ab68Smrg case FcVStackInteger: 1425ca08ab68Smrg if (!FcCharSetAddChar (charset, vstack->u.integer)) 1426ca08ab68Smrg { 1427ca08ab68Smrg FcConfigMessage (parse, FcSevereWarning, "invalid character: 0x%04x", vstack->u.integer); 1428ca08ab68Smrg } 1429ca08ab68Smrg else 1430ca08ab68Smrg n++; 1431ca08ab68Smrg break; 1432ca08ab68Smrg case FcVStackRange: 1433ca08ab68Smrg if (vstack->u.range.begin <= vstack->u.range.end) 1434ca08ab68Smrg { 1435ca08ab68Smrg for (i = vstack->u.range.begin; i <= vstack->u.range.end; i++) 1436ca08ab68Smrg { 1437ca08ab68Smrg if (!FcCharSetAddChar (charset, i)) 1438ca08ab68Smrg { 1439ca08ab68Smrg FcConfigMessage (parse, FcSevereWarning, "invalid character: 0x%04x", i); 1440ca08ab68Smrg } 1441ca08ab68Smrg else 1442ca08ab68Smrg n++; 1443ca08ab68Smrg } 1444ca08ab68Smrg } 1445ca08ab68Smrg break; 1446ca08ab68Smrg default: 1447ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "invalid element in charset"); 1448ca08ab68Smrg break; 1449ca08ab68Smrg } 1450ca08ab68Smrg FcVStackPopAndDestroy (parse); 1451ca08ab68Smrg } 1452ca08ab68Smrg if (n > 0) 1453ca08ab68Smrg FcVStackPushCharSet (parse, charset); 1454ca08ab68Smrg else 1455ca08ab68Smrg FcCharSetDestroy (charset); 1456ca08ab68Smrg} 1457ca08ab68Smrg 1458ca08ab68Smrgstatic void 1459ca08ab68SmrgFcParseLangSet (FcConfigParse *parse) 1460ca08ab68Smrg{ 1461ca08ab68Smrg FcVStack *vstack; 1462ca08ab68Smrg FcLangSet *langset = FcLangSetCreate (); 1463ca08ab68Smrg int n = 0; 1464ca08ab68Smrg 1465ca08ab68Smrg while ((vstack = FcVStackPeek (parse))) 1466ca08ab68Smrg { 1467ca08ab68Smrg switch (vstack->tag) { 1468ca08ab68Smrg case FcVStackString: 1469ca08ab68Smrg if (!FcLangSetAdd (langset, vstack->u.string)) 1470ca08ab68Smrg { 1471ca08ab68Smrg FcConfigMessage (parse, FcSevereWarning, "invalid langset: %s", vstack->u.string); 1472ca08ab68Smrg } 1473ca08ab68Smrg else 1474ca08ab68Smrg n++; 1475ca08ab68Smrg break; 1476ca08ab68Smrg default: 1477ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "invalid element in langset"); 1478ca08ab68Smrg break; 1479ca08ab68Smrg } 1480ca08ab68Smrg FcVStackPopAndDestroy (parse); 1481ca08ab68Smrg } 1482ca08ab68Smrg if (n > 0) 1483ca08ab68Smrg FcVStackPushLangSet (parse, langset); 1484ca08ab68Smrg else 1485ca08ab68Smrg FcLangSetDestroy (langset); 1486ca08ab68Smrg} 1487ca08ab68Smrg 14882c393a42Smrgstatic FcBool 14892c393a42SmrgFcConfigLexBinding (FcConfigParse *parse, 14902c393a42Smrg const FcChar8 *binding_string, 14912c393a42Smrg FcValueBinding *binding_ret) 14922c393a42Smrg{ 14932c393a42Smrg FcValueBinding binding; 1494ca08ab68Smrg 14952c393a42Smrg if (!binding_string) 14962c393a42Smrg binding = FcValueBindingWeak; 14972c393a42Smrg else 14982c393a42Smrg { 14992c393a42Smrg if (!strcmp ((char *) binding_string, "weak")) 15002c393a42Smrg binding = FcValueBindingWeak; 15012c393a42Smrg else if (!strcmp ((char *) binding_string, "strong")) 15022c393a42Smrg binding = FcValueBindingStrong; 15032c393a42Smrg else if (!strcmp ((char *) binding_string, "same")) 15042c393a42Smrg binding = FcValueBindingSame; 15052c393a42Smrg else 15062c393a42Smrg { 15072c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "invalid binding \"%s\"", binding_string); 15082c393a42Smrg return FcFalse; 15092c393a42Smrg } 15102c393a42Smrg } 15112c393a42Smrg *binding_ret = binding; 15122c393a42Smrg return FcTrue; 15132c393a42Smrg} 15142c393a42Smrg 15152c393a42Smrgstatic void 15162c393a42SmrgFcParseFamilies (FcConfigParse *parse, FcVStackTag tag) 15172c393a42Smrg{ 15182c393a42Smrg FcVStack *vstack; 15192c393a42Smrg FcExpr *left, *expr = 0, *new; 15202c393a42Smrg 1521a6844aabSmrg while ((vstack = FcVStackPeek (parse))) 15222c393a42Smrg { 15232c393a42Smrg if (vstack->tag != FcVStackFamily) 15242c393a42Smrg { 15252c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "non-family"); 1526a6844aabSmrg FcVStackPopAndDestroy (parse); 15272c393a42Smrg continue; 15282c393a42Smrg } 15292c393a42Smrg left = vstack->u.expr; 15302c393a42Smrg vstack->tag = FcVStackNone; 1531a6844aabSmrg FcVStackPopAndDestroy (parse); 15322c393a42Smrg if (expr) 15332c393a42Smrg { 1534a6844aabSmrg new = FcExprCreateOp (parse->config, left, FcOpComma, expr); 15352c393a42Smrg if (!new) 15362c393a42Smrg { 15372c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 15382c393a42Smrg FcExprDestroy (left); 15392c393a42Smrg FcExprDestroy (expr); 15402c393a42Smrg break; 15412c393a42Smrg } 15422c393a42Smrg expr = new; 15432c393a42Smrg } 15442c393a42Smrg else 15452c393a42Smrg expr = left; 15462c393a42Smrg } 15472c393a42Smrg if (expr) 15482c393a42Smrg { 15492c393a42Smrg if (!FcVStackPushExpr (parse, tag, expr)) 15502c393a42Smrg { 15512c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 15522c393a42Smrg FcExprDestroy (expr); 15532c393a42Smrg } 15542c393a42Smrg } 15552c393a42Smrg} 15562c393a42Smrg 15572c393a42Smrgstatic void 15582c393a42SmrgFcParseFamily (FcConfigParse *parse) 15592c393a42Smrg{ 15602c393a42Smrg FcChar8 *s; 15612c393a42Smrg FcExpr *expr; 15622c393a42Smrg 15632c393a42Smrg if (!parse->pstack) 15642c393a42Smrg return; 1565a6844aabSmrg s = FcStrBufDoneStatic (&parse->pstack->str); 15662c393a42Smrg if (!s) 15672c393a42Smrg { 15682c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 15692c393a42Smrg return; 15702c393a42Smrg } 1571a6844aabSmrg expr = FcExprCreateString (parse->config, s); 1572a6844aabSmrg FcStrBufDestroy (&parse->pstack->str); 15732c393a42Smrg if (expr) 15742c393a42Smrg FcVStackPushExpr (parse, FcVStackFamily, expr); 15752c393a42Smrg} 15762c393a42Smrg 15772c393a42Smrgstatic void 15782c393a42SmrgFcParseAlias (FcConfigParse *parse) 15792c393a42Smrg{ 15802c393a42Smrg FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0; 15812c393a42Smrg FcEdit *edit = 0, *next; 15822c393a42Smrg FcVStack *vstack; 1583ca08ab68Smrg FcTest *test = NULL; 15842c393a42Smrg FcValueBinding binding; 15852c393a42Smrg 15862c393a42Smrg if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding)) 15872c393a42Smrg return; 1588a6844aabSmrg while ((vstack = FcVStackPeek (parse))) 15892c393a42Smrg { 15902c393a42Smrg switch (vstack->tag) { 15912c393a42Smrg case FcVStackFamily: 15922c393a42Smrg if (family) 15932c393a42Smrg { 1594ca08ab68Smrg FcConfigMessage (parse, FcSevereWarning, "Having multiple <family> in <alias> isn't supported and may not work as expected"); 1595a6844aabSmrg new = FcExprCreateOp (parse->config, vstack->u.expr, FcOpComma, family); 15962c393a42Smrg if (!new) 15972c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 15982c393a42Smrg else 15992c393a42Smrg family = new; 16002c393a42Smrg } 16012c393a42Smrg else 16022c393a42Smrg new = vstack->u.expr; 16032c393a42Smrg if (new) 16042c393a42Smrg { 16052c393a42Smrg family = new; 16062c393a42Smrg vstack->tag = FcVStackNone; 16072c393a42Smrg } 16082c393a42Smrg break; 16092c393a42Smrg case FcVStackPrefer: 16102c393a42Smrg if (prefer) 16112c393a42Smrg FcExprDestroy (prefer); 16122c393a42Smrg prefer = vstack->u.expr; 16132c393a42Smrg vstack->tag = FcVStackNone; 16142c393a42Smrg break; 16152c393a42Smrg case FcVStackAccept: 16162c393a42Smrg if (accept) 16172c393a42Smrg FcExprDestroy (accept); 16182c393a42Smrg accept = vstack->u.expr; 16192c393a42Smrg vstack->tag = FcVStackNone; 16202c393a42Smrg break; 16212c393a42Smrg case FcVStackDefault: 16222c393a42Smrg if (def) 16232c393a42Smrg FcExprDestroy (def); 16242c393a42Smrg def = vstack->u.expr; 16252c393a42Smrg vstack->tag = FcVStackNone; 16262c393a42Smrg break; 1627ca08ab68Smrg case FcVStackTest: 1628ca08ab68Smrg vstack->u.test->next = test; 1629ca08ab68Smrg test = vstack->u.test; 1630ca08ab68Smrg vstack->tag = FcVStackNone; 1631ca08ab68Smrg break; 16322c393a42Smrg default: 16332c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "bad alias"); 16342c393a42Smrg break; 16352c393a42Smrg } 1636a6844aabSmrg FcVStackPopAndDestroy (parse); 16372c393a42Smrg } 16382c393a42Smrg if (!family) 16392c393a42Smrg { 16402c393a42Smrg FcConfigMessage (parse, FcSevereError, "missing family in alias"); 16412c393a42Smrg if (prefer) 16422c393a42Smrg FcExprDestroy (prefer); 16432c393a42Smrg if (accept) 16442c393a42Smrg FcExprDestroy (accept); 16452c393a42Smrg if (def) 16462c393a42Smrg FcExprDestroy (def); 16472c393a42Smrg return; 16482c393a42Smrg } 16492c393a42Smrg if (prefer) 16502c393a42Smrg { 1651ca08ab68Smrg edit = FcEditCreate (parse, 16522c393a42Smrg FC_FAMILY_OBJECT, 16532c393a42Smrg FcOpPrepend, 16542c393a42Smrg prefer, 16552c393a42Smrg binding); 16562c393a42Smrg if (edit) 16572c393a42Smrg edit->next = 0; 16582c393a42Smrg else 16592c393a42Smrg FcExprDestroy (prefer); 16602c393a42Smrg } 16612c393a42Smrg if (accept) 16622c393a42Smrg { 16632c393a42Smrg next = edit; 16642c393a42Smrg edit = FcEditCreate (parse, 16652c393a42Smrg FC_FAMILY_OBJECT, 16662c393a42Smrg FcOpAppend, 16672c393a42Smrg accept, 16682c393a42Smrg binding); 16692c393a42Smrg if (edit) 16702c393a42Smrg edit->next = next; 16712c393a42Smrg else 16722c393a42Smrg FcExprDestroy (accept); 16732c393a42Smrg } 16742c393a42Smrg if (def) 16752c393a42Smrg { 16762c393a42Smrg next = edit; 16772c393a42Smrg edit = FcEditCreate (parse, 16782c393a42Smrg FC_FAMILY_OBJECT, 16792c393a42Smrg FcOpAppendLast, 16802c393a42Smrg def, 16812c393a42Smrg binding); 16822c393a42Smrg if (edit) 16832c393a42Smrg edit->next = next; 16842c393a42Smrg else 16852c393a42Smrg FcExprDestroy (def); 16862c393a42Smrg } 16872c393a42Smrg if (edit) 16882c393a42Smrg { 1689ca08ab68Smrg FcTest *t = FcTestCreate (parse, FcMatchPattern, 1690ca08ab68Smrg FcQualAny, 1691ca08ab68Smrg (FcChar8 *) FC_FAMILY, 1692ca08ab68Smrg FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks), 1693ca08ab68Smrg family); 1694ca08ab68Smrg if (test) 1695ca08ab68Smrg { 1696ca08ab68Smrg FcTest *p = test; 1697ca08ab68Smrg 1698ca08ab68Smrg while (p->next) 1699ca08ab68Smrg p = p->next; 1700ca08ab68Smrg p->next = t; 1701ca08ab68Smrg } 1702ca08ab68Smrg else 1703ca08ab68Smrg test = t; 17042c393a42Smrg if (test) 17052c393a42Smrg if (!FcConfigAddEdit (parse->config, test, edit, FcMatchPattern)) 17062c393a42Smrg FcTestDestroy (test); 17072c393a42Smrg } 17082c393a42Smrg else 17092c393a42Smrg FcExprDestroy (family); 17102c393a42Smrg} 17112c393a42Smrg 17122c393a42Smrgstatic FcExpr * 17132c393a42SmrgFcPopExpr (FcConfigParse *parse) 17142c393a42Smrg{ 1715a6844aabSmrg FcVStack *vstack = FcVStackPeek (parse); 17162c393a42Smrg FcExpr *expr = 0; 17172c393a42Smrg if (!vstack) 17182c393a42Smrg return 0; 17192c393a42Smrg switch (vstack->tag) { 17202c393a42Smrg case FcVStackNone: 17212c393a42Smrg break; 17222c393a42Smrg case FcVStackString: 17232c393a42Smrg case FcVStackFamily: 1724a6844aabSmrg expr = FcExprCreateString (parse->config, vstack->u.string); 17252c393a42Smrg break; 17262c393a42Smrg case FcVStackField: 1727a6844aabSmrg expr = FcExprCreateField (parse->config, (char *) vstack->u.string); 17282c393a42Smrg break; 17292c393a42Smrg case FcVStackConstant: 1730a6844aabSmrg expr = FcExprCreateConst (parse->config, vstack->u.string); 17312c393a42Smrg break; 17322c393a42Smrg case FcVStackGlob: 17332c393a42Smrg /* XXX: What's the correct action here? (CDW) */ 17342c393a42Smrg break; 17352c393a42Smrg case FcVStackPrefer: 17362c393a42Smrg case FcVStackAccept: 17372c393a42Smrg case FcVStackDefault: 17382c393a42Smrg expr = vstack->u.expr; 17392c393a42Smrg vstack->tag = FcVStackNone; 17402c393a42Smrg break; 17412c393a42Smrg case FcVStackInteger: 1742a6844aabSmrg expr = FcExprCreateInteger (parse->config, vstack->u.integer); 17432c393a42Smrg break; 17442c393a42Smrg case FcVStackDouble: 1745a6844aabSmrg expr = FcExprCreateDouble (parse->config, vstack->u._double); 17462c393a42Smrg break; 17472c393a42Smrg case FcVStackMatrix: 1748a6844aabSmrg expr = FcExprCreateMatrix (parse->config, vstack->u.matrix); 17492c393a42Smrg break; 1750ca08ab68Smrg case FcVStackRange: 1751ca08ab68Smrg break; 17522c393a42Smrg case FcVStackBool: 1753a6844aabSmrg expr = FcExprCreateBool (parse->config, vstack->u.bool_); 17542c393a42Smrg break; 1755ca08ab68Smrg case FcVStackCharSet: 1756ca08ab68Smrg expr = FcExprCreateCharSet (parse->config, vstack->u.charset); 1757ca08ab68Smrg break; 1758ca08ab68Smrg case FcVStackLangSet: 1759ca08ab68Smrg expr = FcExprCreateLangSet (parse->config, vstack->u.langset); 1760ca08ab68Smrg break; 17612c393a42Smrg case FcVStackTest: 17622c393a42Smrg break; 17632c393a42Smrg case FcVStackExpr: 17642c393a42Smrg expr = vstack->u.expr; 17652c393a42Smrg vstack->tag = FcVStackNone; 17662c393a42Smrg break; 17672c393a42Smrg case FcVStackEdit: 17682c393a42Smrg break; 17692c393a42Smrg default: 17702c393a42Smrg break; 17712c393a42Smrg } 1772a6844aabSmrg FcVStackPopAndDestroy (parse); 17732c393a42Smrg return expr; 17742c393a42Smrg} 17752c393a42Smrg 17762c393a42Smrg/* 17772c393a42Smrg * This builds a tree of binary operations. Note 17782c393a42Smrg * that every operator is defined so that if only 17792c393a42Smrg * a single operand is contained, the value of the 17802c393a42Smrg * whole expression is the value of the operand. 17812c393a42Smrg * 17822c393a42Smrg * This code reduces in that case to returning that 17832c393a42Smrg * operand. 17842c393a42Smrg */ 17852c393a42Smrgstatic FcExpr * 17862c393a42SmrgFcPopBinary (FcConfigParse *parse, FcOp op) 17872c393a42Smrg{ 17882c393a42Smrg FcExpr *left, *expr = 0, *new; 17892c393a42Smrg 17902c393a42Smrg while ((left = FcPopExpr (parse))) 17912c393a42Smrg { 17922c393a42Smrg if (expr) 17932c393a42Smrg { 1794a6844aabSmrg new = FcExprCreateOp (parse->config, left, op, expr); 17952c393a42Smrg if (!new) 17962c393a42Smrg { 17972c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 17982c393a42Smrg FcExprDestroy (left); 17992c393a42Smrg FcExprDestroy (expr); 18002c393a42Smrg return 0; 18012c393a42Smrg } 18022c393a42Smrg expr = new; 18032c393a42Smrg } 18042c393a42Smrg else 18052c393a42Smrg expr = left; 18062c393a42Smrg } 18072c393a42Smrg return expr; 18082c393a42Smrg} 18092c393a42Smrg 18102c393a42Smrgstatic void 18112c393a42SmrgFcParseBinary (FcConfigParse *parse, FcOp op) 18122c393a42Smrg{ 18132c393a42Smrg FcExpr *expr = FcPopBinary (parse, op); 18142c393a42Smrg if (expr) 18152c393a42Smrg FcVStackPushExpr (parse, FcVStackExpr, expr); 18162c393a42Smrg} 18172c393a42Smrg 18182c393a42Smrg/* 18192c393a42Smrg * This builds a a unary operator, it consumes only 18202c393a42Smrg * a single operand 18212c393a42Smrg */ 18222c393a42Smrg 18232c393a42Smrgstatic FcExpr * 18242c393a42SmrgFcPopUnary (FcConfigParse *parse, FcOp op) 18252c393a42Smrg{ 18262c393a42Smrg FcExpr *operand, *new = 0; 18272c393a42Smrg 18282c393a42Smrg if ((operand = FcPopExpr (parse))) 18292c393a42Smrg { 1830a6844aabSmrg new = FcExprCreateOp (parse->config, operand, op, 0); 18312c393a42Smrg if (!new) 18322c393a42Smrg { 18332c393a42Smrg FcExprDestroy (operand); 18342c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 18352c393a42Smrg } 18362c393a42Smrg } 18372c393a42Smrg return new; 18382c393a42Smrg} 18392c393a42Smrg 18402c393a42Smrgstatic void 18412c393a42SmrgFcParseUnary (FcConfigParse *parse, FcOp op) 18422c393a42Smrg{ 18432c393a42Smrg FcExpr *expr = FcPopUnary (parse, op); 18442c393a42Smrg if (expr) 18452c393a42Smrg FcVStackPushExpr (parse, FcVStackExpr, expr); 18462c393a42Smrg} 18472c393a42Smrg 1848ca08ab68Smrgstatic void 1849ca08ab68SmrgFcParseDir (FcConfigParse *parse) 1850ca08ab68Smrg{ 1851ca08ab68Smrg const FcChar8 *attr, *data; 1852ca08ab68Smrg FcChar8 *prefix = NULL; 1853ca08ab68Smrg#ifdef _WIN32 1854ca08ab68Smrg FcChar8 buffer[1000]; 1855ca08ab68Smrg#endif 1856ca08ab68Smrg 1857ca08ab68Smrg attr = FcConfigGetAttribute (parse, "prefix"); 1858ca08ab68Smrg if (attr && FcStrCmp (attr, (const FcChar8 *)"xdg") == 0) 1859ca08ab68Smrg prefix = FcConfigXdgDataHome (); 1860ca08ab68Smrg data = FcStrBufDoneStatic (&parse->pstack->str); 1861ca08ab68Smrg if (!data) 1862ca08ab68Smrg { 1863ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 1864ca08ab68Smrg goto bail; 1865ca08ab68Smrg } 1866ca08ab68Smrg if (prefix) 1867ca08ab68Smrg { 1868ca08ab68Smrg size_t plen = strlen ((const char *)prefix); 1869ca08ab68Smrg size_t dlen = strlen ((const char *)data); 1870ca08ab68Smrg 1871ca08ab68Smrg FcMemFree (FC_MEM_STRING, plen + 1); 1872ca08ab68Smrg prefix = realloc (prefix, plen + 1 + dlen + 1); 1873ca08ab68Smrg if (!prefix) 1874ca08ab68Smrg { 1875ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 1876ca08ab68Smrg goto bail; 1877ca08ab68Smrg } 1878ca08ab68Smrg FcMemAlloc (FC_MEM_STRING, plen + 1 + dlen + 1); 1879ca08ab68Smrg prefix[plen] = FC_DIR_SEPARATOR; 1880ca08ab68Smrg memcpy (&prefix[plen + 1], data, dlen); 1881ca08ab68Smrg prefix[plen + 1 + dlen] = 0; 1882ca08ab68Smrg data = prefix; 1883ca08ab68Smrg } 1884ca08ab68Smrg#ifdef _WIN32 1885ca08ab68Smrg if (strcmp ((const char *) data, "CUSTOMFONTDIR") == 0) 1886ca08ab68Smrg { 1887ca08ab68Smrg char *p; 1888ca08ab68Smrg data = buffer; 1889ca08ab68Smrg if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20)) 1890ca08ab68Smrg { 1891ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed"); 1892ca08ab68Smrg goto bail; 1893ca08ab68Smrg } 1894ca08ab68Smrg /* 1895ca08ab68Smrg * Must use the multi-byte aware function to search 1896ca08ab68Smrg * for backslash because East Asian double-byte code 1897ca08ab68Smrg * pages have characters with backslash as the second 1898ca08ab68Smrg * byte. 1899ca08ab68Smrg */ 1900ca08ab68Smrg p = _mbsrchr (data, '\\'); 1901ca08ab68Smrg if (p) *p = '\0'; 1902ca08ab68Smrg strcat (data, "\\fonts"); 1903ca08ab68Smrg } 1904ca08ab68Smrg else if (strcmp ((const char *) data, "APPSHAREFONTDIR") == 0) 1905ca08ab68Smrg { 1906ca08ab68Smrg char *p; 1907ca08ab68Smrg data = buffer; 1908ca08ab68Smrg if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20)) 1909ca08ab68Smrg { 1910ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed"); 1911ca08ab68Smrg goto bail; 1912ca08ab68Smrg } 1913ca08ab68Smrg p = _mbsrchr (data, '\\'); 1914ca08ab68Smrg if (p) *p = '\0'; 1915ca08ab68Smrg strcat (data, "\\..\\share\\fonts"); 1916ca08ab68Smrg } 1917ca08ab68Smrg else if (strcmp ((const char *) data, "WINDOWSFONTDIR") == 0) 1918ca08ab68Smrg { 1919ca08ab68Smrg int rc; 1920ca08ab68Smrg data = buffer; 1921ca08ab68Smrg rc = pGetSystemWindowsDirectory ((LPSTR) buffer, sizeof (buffer) - 20); 1922ca08ab68Smrg if (rc == 0 || rc > sizeof (buffer) - 20) 1923ca08ab68Smrg { 1924ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "GetSystemWindowsDirectory failed"); 1925ca08ab68Smrg goto bail; 1926ca08ab68Smrg } 1927ca08ab68Smrg if (data [strlen ((const char *) data) - 1] != '\\') 1928ca08ab68Smrg strcat (data, "\\"); 1929ca08ab68Smrg strcat (data, "fonts"); 1930ca08ab68Smrg } 1931ca08ab68Smrg#endif 1932ca08ab68Smrg if (strlen ((char *) data) == 0) 1933ca08ab68Smrg FcConfigMessage (parse, FcSevereWarning, "empty font directory name ignored"); 1934ca08ab68Smrg else if (!FcStrUsesHome (data) || FcConfigHome ()) 1935ca08ab68Smrg { 1936ca08ab68Smrg if (!FcConfigAddDir (parse->config, data)) 1937ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", data); 1938ca08ab68Smrg } 1939ca08ab68Smrg FcStrBufDestroy (&parse->pstack->str); 1940ca08ab68Smrg 1941ca08ab68Smrg bail: 1942ca08ab68Smrg if (prefix) 1943ca08ab68Smrg FcStrFree (prefix); 1944ca08ab68Smrg} 1945ca08ab68Smrg 1946ca08ab68Smrgstatic void 1947ca08ab68SmrgFcParseCacheDir (FcConfigParse *parse) 1948ca08ab68Smrg{ 1949ca08ab68Smrg const FcChar8 *attr; 1950ca08ab68Smrg FcChar8 *prefix = NULL, *data; 1951ca08ab68Smrg 1952ca08ab68Smrg attr = FcConfigGetAttribute (parse, "prefix"); 1953ca08ab68Smrg if (attr && FcStrCmp (attr, (const FcChar8 *)"xdg") == 0) 1954ca08ab68Smrg prefix = FcConfigXdgCacheHome (); 1955ca08ab68Smrg data = FcStrBufDone (&parse->pstack->str); 1956ca08ab68Smrg if (!data) 1957ca08ab68Smrg { 1958ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 1959ca08ab68Smrg goto bail; 1960ca08ab68Smrg } 1961ca08ab68Smrg if (prefix) 1962ca08ab68Smrg { 1963ca08ab68Smrg size_t plen = strlen ((const char *)prefix); 1964ca08ab68Smrg size_t dlen = strlen ((const char *)data); 1965ca08ab68Smrg 1966ca08ab68Smrg FcMemFree (FC_MEM_STRING, plen + 1); 1967ca08ab68Smrg prefix = realloc (prefix, plen + 1 + dlen + 1); 1968ca08ab68Smrg if (!prefix) 1969ca08ab68Smrg { 1970ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 1971ca08ab68Smrg goto bail; 1972ca08ab68Smrg } 1973ca08ab68Smrg FcMemAlloc (FC_MEM_STRING, plen + 1 + dlen + 1); 1974ca08ab68Smrg prefix[plen] = FC_DIR_SEPARATOR; 1975ca08ab68Smrg memcpy (&prefix[plen + 1], data, dlen); 1976ca08ab68Smrg prefix[plen + 1 + dlen] = 0; 1977ca08ab68Smrg FcStrFree (data); 1978ca08ab68Smrg data = prefix; 1979ca08ab68Smrg } 1980ca08ab68Smrg#ifdef _WIN32 1981ca08ab68Smrg if (strcmp ((const char *) data, "WINDOWSTEMPDIR_FONTCONFIG_CACHE") == 0) 1982ca08ab68Smrg { 1983ca08ab68Smrg int rc; 1984ca08ab68Smrg FcStrFree (data); 1985ca08ab68Smrg data = malloc (1000); 1986ca08ab68Smrg if (!data) 1987ca08ab68Smrg { 1988ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 1989ca08ab68Smrg goto bail; 1990ca08ab68Smrg } 1991ca08ab68Smrg FcMemAlloc (FC_MEM_STRING, 1000); 1992ca08ab68Smrg rc = GetTempPath (800, (LPSTR) data); 1993ca08ab68Smrg if (rc == 0 || rc > 800) 1994ca08ab68Smrg { 1995ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "GetTempPath failed"); 1996ca08ab68Smrg goto bail; 1997ca08ab68Smrg } 1998ca08ab68Smrg if (data [strlen ((const char *) data) - 1] != '\\') 1999ca08ab68Smrg strcat (data, "\\"); 2000ca08ab68Smrg strcat (data, "fontconfig\\cache"); 2001ca08ab68Smrg } 2002ca08ab68Smrg else if (strcmp ((const char *) data, "LOCAL_APPDATA_FONTCONFIG_CACHE") == 0) 2003ca08ab68Smrg { 2004ca08ab68Smrg char szFPath[MAX_PATH + 1]; 2005ca08ab68Smrg size_t len; 2006ca08ab68Smrg 2007ca08ab68Smrg if (!(pSHGetFolderPathA && SUCCEEDED(pSHGetFolderPathA(NULL, /* CSIDL_LOCAL_APPDATA */ 28, NULL, 0, szFPath)))) 2008ca08ab68Smrg { 2009ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "SHGetFolderPathA failed"); 2010ca08ab68Smrg goto bail; 2011ca08ab68Smrg } 2012ca08ab68Smrg strncat(szFPath, "\\fontconfig\\cache", MAX_PATH - 1 - strlen(szFPath)); 2013ca08ab68Smrg len = strlen(szFPath) + 1; 2014ca08ab68Smrg FcStrFree (data); 2015ca08ab68Smrg data = malloc(len); 2016ca08ab68Smrg if (!data) 2017ca08ab68Smrg { 2018ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 2019ca08ab68Smrg goto bail; 2020ca08ab68Smrg } 2021ca08ab68Smrg FcMemAlloc (FC_MEM_STRING, len); 2022ca08ab68Smrg strncpy((char *) data, szFPath, len); 2023ca08ab68Smrg } 2024ca08ab68Smrg#endif 2025ca08ab68Smrg if (strlen ((char *) data) == 0) 2026ca08ab68Smrg FcConfigMessage (parse, FcSevereWarning, "empty cache directory name ignored"); 2027ca08ab68Smrg else if (!FcStrUsesHome (data) || FcConfigHome ()) 2028ca08ab68Smrg { 2029ca08ab68Smrg if (!FcConfigAddCacheDir (parse->config, data)) 2030ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "out of memory; cannot add cache directory %s", data); 2031ca08ab68Smrg } 2032ca08ab68Smrg FcStrBufDestroy (&parse->pstack->str); 2033ca08ab68Smrg 2034ca08ab68Smrg bail: 2035ca08ab68Smrg if (data) 2036ca08ab68Smrg FcStrFree (data); 2037ca08ab68Smrg} 2038ca08ab68Smrg 20392c393a42Smrgstatic void 20402c393a42SmrgFcParseInclude (FcConfigParse *parse) 20412c393a42Smrg{ 20422c393a42Smrg FcChar8 *s; 2043ca08ab68Smrg const FcChar8 *attr; 20442c393a42Smrg FcBool ignore_missing = FcFalse; 2045ca08ab68Smrg FcBool deprecated = FcFalse; 2046ca08ab68Smrg FcChar8 *prefix = NULL; 2047ca08ab68Smrg 2048a6844aabSmrg s = FcStrBufDoneStatic (&parse->pstack->str); 20492c393a42Smrg if (!s) 20502c393a42Smrg { 20512c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 2052ca08ab68Smrg goto bail; 20532c393a42Smrg } 2054ca08ab68Smrg attr = FcConfigGetAttribute (parse, "ignore_missing"); 2055ca08ab68Smrg if (attr && FcConfigLexBool (parse, (FcChar8 *) attr) == FcTrue) 20562c393a42Smrg ignore_missing = FcTrue; 2057ca08ab68Smrg attr = FcConfigGetAttribute (parse, "deprecated"); 2058ca08ab68Smrg if (attr && FcConfigLexBool (parse, (FcChar8 *) attr) == FcTrue) 2059ca08ab68Smrg deprecated = FcTrue; 2060ca08ab68Smrg attr = FcConfigGetAttribute (parse, "prefix"); 2061ca08ab68Smrg if (attr && FcStrCmp (attr, (const FcChar8 *)"xdg") == 0) 2062ca08ab68Smrg prefix = FcConfigXdgConfigHome (); 2063ca08ab68Smrg if (prefix) 2064ca08ab68Smrg { 2065ca08ab68Smrg size_t plen = strlen ((const char *)prefix); 2066ca08ab68Smrg size_t dlen = strlen ((const char *)s); 2067ca08ab68Smrg 2068ca08ab68Smrg FcMemFree (FC_MEM_STRING, plen + 1); 2069ca08ab68Smrg prefix = realloc (prefix, plen + 1 + dlen + 1); 2070ca08ab68Smrg if (!prefix) 2071ca08ab68Smrg { 2072ca08ab68Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 2073ca08ab68Smrg goto bail; 2074ca08ab68Smrg } 2075ca08ab68Smrg FcMemAlloc (FC_MEM_STRING, plen + 1 + dlen + 1); 2076ca08ab68Smrg prefix[plen] = FC_DIR_SEPARATOR; 2077ca08ab68Smrg memcpy (&prefix[plen + 1], s, dlen); 2078ca08ab68Smrg prefix[plen + 1 + dlen] = 0; 2079ca08ab68Smrg s = prefix; 2080ca08ab68Smrg } 20812c393a42Smrg if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing)) 20822c393a42Smrg parse->error = FcTrue; 2083ca08ab68Smrg else 2084ca08ab68Smrg { 2085ca08ab68Smrg FcChar8 *filename; 2086ca08ab68Smrg 2087ca08ab68Smrg filename = FcConfigFilename(s); 2088ca08ab68Smrg if ((deprecated == FcTrue) && filename) 2089ca08ab68Smrg { 2090ca08ab68Smrg FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated.", s); 2091ca08ab68Smrg } 2092ca08ab68Smrg if(filename) 2093ca08ab68Smrg FcStrFree(filename); 2094ca08ab68Smrg } 2095a6844aabSmrg FcStrBufDestroy (&parse->pstack->str); 2096ca08ab68Smrg 2097ca08ab68Smrg bail: 2098ca08ab68Smrg if (prefix) 2099ca08ab68Smrg FcStrFree (prefix); 21002c393a42Smrg} 21012c393a42Smrg 21022c393a42Smrgtypedef struct _FcOpMap { 21032c393a42Smrg char name[16]; 21042c393a42Smrg FcOp op; 21052c393a42Smrg} FcOpMap; 21062c393a42Smrg 21072c393a42Smrgstatic FcOp 21082c393a42SmrgFcConfigLexOp (const FcChar8 *op, const FcOpMap *map, int nmap) 21092c393a42Smrg{ 21102c393a42Smrg int i; 21112c393a42Smrg 21122c393a42Smrg for (i = 0; i < nmap; i++) 2113ca08ab68Smrg if (!strcmp ((char *) op, map[i].name)) 21142c393a42Smrg return map[i].op; 21152c393a42Smrg return FcOpInvalid; 21162c393a42Smrg} 21172c393a42Smrg 21182c393a42Smrgstatic const FcOpMap fcCompareOps[] = { 21192c393a42Smrg { "eq", FcOpEqual }, 21202c393a42Smrg { "not_eq", FcOpNotEqual }, 21212c393a42Smrg { "less", FcOpLess }, 21222c393a42Smrg { "less_eq", FcOpLessEqual }, 21232c393a42Smrg { "more", FcOpMore }, 21242c393a42Smrg { "more_eq", FcOpMoreEqual }, 21252c393a42Smrg { "contains", FcOpContains }, 21262c393a42Smrg { "not_contains", FcOpNotContains } 21272c393a42Smrg}; 21282c393a42Smrg 21292c393a42Smrg#define NUM_COMPARE_OPS (int) (sizeof fcCompareOps / sizeof fcCompareOps[0]) 21302c393a42Smrg 21312c393a42Smrgstatic FcOp 21322c393a42SmrgFcConfigLexCompare (const FcChar8 *compare) 21332c393a42Smrg{ 21342c393a42Smrg return FcConfigLexOp (compare, fcCompareOps, NUM_COMPARE_OPS); 21352c393a42Smrg} 21362c393a42Smrg 21372c393a42Smrgstatic void 21382c393a42SmrgFcParseTest (FcConfigParse *parse) 21392c393a42Smrg{ 21402c393a42Smrg const FcChar8 *kind_string; 21412c393a42Smrg FcMatchKind kind; 21422c393a42Smrg const FcChar8 *qual_string; 21432c393a42Smrg FcQual qual; 21442c393a42Smrg const FcChar8 *name; 21452c393a42Smrg const FcChar8 *compare_string; 21462c393a42Smrg FcOp compare; 21472c393a42Smrg FcExpr *expr; 21482c393a42Smrg FcTest *test; 2149ca08ab68Smrg const FcChar8 *iblanks_string; 2150ca08ab68Smrg int flags = 0; 21512c393a42Smrg 21522c393a42Smrg kind_string = FcConfigGetAttribute (parse, "target"); 21532c393a42Smrg if (!kind_string) 21542c393a42Smrg kind = FcMatchDefault; 21552c393a42Smrg else 21562c393a42Smrg { 21572c393a42Smrg if (!strcmp ((char *) kind_string, "pattern")) 21582c393a42Smrg kind = FcMatchPattern; 21592c393a42Smrg else if (!strcmp ((char *) kind_string, "font")) 21602c393a42Smrg kind = FcMatchFont; 21612c393a42Smrg else if (!strcmp ((char *) kind_string, "scan")) 21622c393a42Smrg kind = FcMatchScan; 21632c393a42Smrg else if (!strcmp ((char *) kind_string, "default")) 21642c393a42Smrg kind = FcMatchDefault; 21652c393a42Smrg else 21662c393a42Smrg { 21672c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "invalid test target \"%s\"", kind_string); 21682c393a42Smrg return; 21692c393a42Smrg } 21702c393a42Smrg } 21712c393a42Smrg qual_string = FcConfigGetAttribute (parse, "qual"); 21722c393a42Smrg if (!qual_string) 21732c393a42Smrg qual = FcQualAny; 21742c393a42Smrg else 21752c393a42Smrg { 21762c393a42Smrg if (!strcmp ((char *) qual_string, "any")) 21772c393a42Smrg qual = FcQualAny; 21782c393a42Smrg else if (!strcmp ((char *) qual_string, "all")) 21792c393a42Smrg qual = FcQualAll; 21802c393a42Smrg else if (!strcmp ((char *) qual_string, "first")) 21812c393a42Smrg qual = FcQualFirst; 21822c393a42Smrg else if (!strcmp ((char *) qual_string, "not_first")) 21832c393a42Smrg qual = FcQualNotFirst; 21842c393a42Smrg else 21852c393a42Smrg { 21862c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "invalid test qual \"%s\"", qual_string); 21872c393a42Smrg return; 21882c393a42Smrg } 21892c393a42Smrg } 21902c393a42Smrg name = FcConfigGetAttribute (parse, "name"); 21912c393a42Smrg if (!name) 21922c393a42Smrg { 21932c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "missing test name"); 21942c393a42Smrg return; 21952c393a42Smrg } 21962c393a42Smrg compare_string = FcConfigGetAttribute (parse, "compare"); 21972c393a42Smrg if (!compare_string) 21982c393a42Smrg compare = FcOpEqual; 21992c393a42Smrg else 22002c393a42Smrg { 22012c393a42Smrg compare = FcConfigLexCompare (compare_string); 22022c393a42Smrg if (compare == FcOpInvalid) 22032c393a42Smrg { 22042c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "invalid test compare \"%s\"", compare_string); 22052c393a42Smrg return; 22062c393a42Smrg } 22072c393a42Smrg } 2208ca08ab68Smrg iblanks_string = FcConfigGetAttribute (parse, "ignore-blanks"); 2209ca08ab68Smrg if (iblanks_string) 2210ca08ab68Smrg { 2211ca08ab68Smrg FcBool f = FcFalse; 2212ca08ab68Smrg 2213ca08ab68Smrg if (!FcNameBool (iblanks_string, &f)) 2214ca08ab68Smrg { 2215ca08ab68Smrg FcConfigMessage (parse, 2216ca08ab68Smrg FcSevereWarning, 2217ca08ab68Smrg "invalid test ignore-blanks \"%s\"", iblanks_string); 2218ca08ab68Smrg } 2219ca08ab68Smrg if (f) 2220ca08ab68Smrg flags |= FcOpFlagIgnoreBlanks; 2221ca08ab68Smrg } 22222c393a42Smrg expr = FcPopBinary (parse, FcOpComma); 22232c393a42Smrg if (!expr) 22242c393a42Smrg { 22252c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "missing test expression"); 22262c393a42Smrg return; 22272c393a42Smrg } 2228ca08ab68Smrg if (expr->op == FcOpComma) 2229ca08ab68Smrg { 2230ca08ab68Smrg FcConfigMessage (parse, FcSevereWarning, "Having multiple values in <test> isn't supported and may not work as expected"); 2231ca08ab68Smrg } 2232ca08ab68Smrg test = FcTestCreate (parse, kind, qual, name, FC_OP (compare, flags), expr); 22332c393a42Smrg if (!test) 22342c393a42Smrg { 22352c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 22362c393a42Smrg return; 22372c393a42Smrg } 22382c393a42Smrg FcVStackPushTest (parse, test); 22392c393a42Smrg} 22402c393a42Smrg 22412c393a42Smrgstatic const FcOpMap fcModeOps[] = { 22422c393a42Smrg { "assign", FcOpAssign }, 22432c393a42Smrg { "assign_replace", FcOpAssignReplace }, 22442c393a42Smrg { "prepend", FcOpPrepend }, 22452c393a42Smrg { "prepend_first", FcOpPrependFirst }, 22462c393a42Smrg { "append", FcOpAppend }, 22472c393a42Smrg { "append_last", FcOpAppendLast }, 22482c393a42Smrg}; 22492c393a42Smrg 22502c393a42Smrg#define NUM_MODE_OPS (int) (sizeof fcModeOps / sizeof fcModeOps[0]) 22512c393a42Smrg 22522c393a42Smrgstatic FcOp 22532c393a42SmrgFcConfigLexMode (const FcChar8 *mode) 22542c393a42Smrg{ 22552c393a42Smrg return FcConfigLexOp (mode, fcModeOps, NUM_MODE_OPS); 22562c393a42Smrg} 22572c393a42Smrg 22582c393a42Smrgstatic void 22592c393a42SmrgFcParseEdit (FcConfigParse *parse) 22602c393a42Smrg{ 22612c393a42Smrg const FcChar8 *name; 22622c393a42Smrg const FcChar8 *mode_string; 22632c393a42Smrg FcOp mode; 22642c393a42Smrg FcValueBinding binding; 22652c393a42Smrg FcExpr *expr; 22662c393a42Smrg FcEdit *edit; 22672c393a42Smrg 22682c393a42Smrg name = FcConfigGetAttribute (parse, "name"); 22692c393a42Smrg if (!name) 22702c393a42Smrg { 22712c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "missing edit name"); 22722c393a42Smrg return; 22732c393a42Smrg } 22742c393a42Smrg mode_string = FcConfigGetAttribute (parse, "mode"); 22752c393a42Smrg if (!mode_string) 22762c393a42Smrg mode = FcOpAssign; 22772c393a42Smrg else 22782c393a42Smrg { 22792c393a42Smrg mode = FcConfigLexMode (mode_string); 22802c393a42Smrg if (mode == FcOpInvalid) 22812c393a42Smrg { 22822c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "invalid edit mode \"%s\"", mode_string); 22832c393a42Smrg return; 22842c393a42Smrg } 22852c393a42Smrg } 22862c393a42Smrg if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding)) 22872c393a42Smrg return; 22882c393a42Smrg 22892c393a42Smrg expr = FcPopBinary (parse, FcOpComma); 22902c393a42Smrg edit = FcEditCreate (parse, FcObjectFromName ((char *) name), 22912c393a42Smrg mode, expr, binding); 22922c393a42Smrg if (!edit) 22932c393a42Smrg { 22942c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 22952c393a42Smrg FcExprDestroy (expr); 22962c393a42Smrg return; 22972c393a42Smrg } 22982c393a42Smrg if (!FcVStackPushEdit (parse, edit)) 22992c393a42Smrg FcEditDestroy (edit); 23002c393a42Smrg} 23012c393a42Smrg 23022c393a42Smrgstatic void 23032c393a42SmrgFcParseMatch (FcConfigParse *parse) 23042c393a42Smrg{ 23052c393a42Smrg const FcChar8 *kind_name; 23062c393a42Smrg FcMatchKind kind; 23072c393a42Smrg FcTest *test = 0; 23082c393a42Smrg FcEdit *edit = 0; 23092c393a42Smrg FcVStack *vstack; 23102c393a42Smrg 23112c393a42Smrg kind_name = FcConfigGetAttribute (parse, "target"); 23122c393a42Smrg if (!kind_name) 23132c393a42Smrg kind = FcMatchPattern; 23142c393a42Smrg else 23152c393a42Smrg { 23162c393a42Smrg if (!strcmp ((char *) kind_name, "pattern")) 23172c393a42Smrg kind = FcMatchPattern; 23182c393a42Smrg else if (!strcmp ((char *) kind_name, "font")) 23192c393a42Smrg kind = FcMatchFont; 23202c393a42Smrg else if (!strcmp ((char *) kind_name, "scan")) 23212c393a42Smrg kind = FcMatchScan; 23222c393a42Smrg else 23232c393a42Smrg { 23242c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "invalid match target \"%s\"", kind_name); 23252c393a42Smrg return; 23262c393a42Smrg } 23272c393a42Smrg } 2328a6844aabSmrg while ((vstack = FcVStackPeek (parse))) 23292c393a42Smrg { 23302c393a42Smrg switch (vstack->tag) { 23312c393a42Smrg case FcVStackTest: 23322c393a42Smrg vstack->u.test->next = test; 23332c393a42Smrg test = vstack->u.test; 23342c393a42Smrg vstack->tag = FcVStackNone; 23352c393a42Smrg break; 23362c393a42Smrg case FcVStackEdit: 23372c393a42Smrg vstack->u.edit->next = edit; 23382c393a42Smrg edit = vstack->u.edit; 23392c393a42Smrg vstack->tag = FcVStackNone; 23402c393a42Smrg if (kind == FcMatchScan && edit->object > FC_MAX_BASE_OBJECT) 23412c393a42Smrg { 2342ca08ab68Smrg FcConfigMessage (parse, FcSevereError, 23432c393a42Smrg "<match target=\"scan\"> cannot edit user-defined object \"%s\"", 23442c393a42Smrg FcObjectName(edit->object)); 23452c393a42Smrg } 23462c393a42Smrg break; 23472c393a42Smrg default: 23482c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "invalid match element"); 23492c393a42Smrg break; 23502c393a42Smrg } 2351a6844aabSmrg FcVStackPopAndDestroy (parse); 23522c393a42Smrg } 23532c393a42Smrg if (!FcConfigAddEdit (parse->config, test, edit, kind)) 23542c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 23552c393a42Smrg} 23562c393a42Smrg 23572c393a42Smrgstatic void 23582c393a42SmrgFcParseAcceptRejectFont (FcConfigParse *parse, FcElement element) 23592c393a42Smrg{ 23602c393a42Smrg FcVStack *vstack; 23612c393a42Smrg 2362a6844aabSmrg while ((vstack = FcVStackPeek (parse))) 23632c393a42Smrg { 23642c393a42Smrg switch (vstack->tag) { 23652c393a42Smrg case FcVStackGlob: 2366ca08ab68Smrg if (!FcConfigGlobAdd (parse->config, 23672c393a42Smrg vstack->u.string, 23682c393a42Smrg element == FcElementAcceptfont)) 23692c393a42Smrg { 23702c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 23712c393a42Smrg } 23722c393a42Smrg break; 23732c393a42Smrg case FcVStackPattern: 23742c393a42Smrg if (!FcConfigPatternsAdd (parse->config, 23752c393a42Smrg vstack->u.pattern, 23762c393a42Smrg element == FcElementAcceptfont)) 23772c393a42Smrg { 23782c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 23792c393a42Smrg } 23802c393a42Smrg else 23812c393a42Smrg vstack->tag = FcVStackNone; 23822c393a42Smrg break; 23832c393a42Smrg default: 23842c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "bad font selector"); 23852c393a42Smrg break; 23862c393a42Smrg } 2387a6844aabSmrg FcVStackPopAndDestroy (parse); 23882c393a42Smrg } 23892c393a42Smrg} 23902c393a42Smrg 23912c393a42Smrg 23922c393a42Smrgstatic FcValue 23932c393a42SmrgFcPopValue (FcConfigParse *parse) 23942c393a42Smrg{ 2395a6844aabSmrg FcVStack *vstack = FcVStackPeek (parse); 23962c393a42Smrg FcValue value; 2397ca08ab68Smrg 23982c393a42Smrg value.type = FcTypeVoid; 2399ca08ab68Smrg 24002c393a42Smrg if (!vstack) 24012c393a42Smrg return value; 2402ca08ab68Smrg 24032c393a42Smrg switch (vstack->tag) { 24042c393a42Smrg case FcVStackString: 2405ca08ab68Smrg value.u.s = FcSharedStr (vstack->u.string); 24062c393a42Smrg if (value.u.s) 24072c393a42Smrg value.type = FcTypeString; 24082c393a42Smrg break; 24092c393a42Smrg case FcVStackConstant: 24102c393a42Smrg if (FcNameConstant (vstack->u.string, &value.u.i)) 24112c393a42Smrg value.type = FcTypeInteger; 24122c393a42Smrg break; 24132c393a42Smrg case FcVStackInteger: 24142c393a42Smrg value.u.i = vstack->u.integer; 24152c393a42Smrg value.type = FcTypeInteger; 24162c393a42Smrg break; 24172c393a42Smrg case FcVStackDouble: 24182c393a42Smrg value.u.d = vstack->u._double; 24192c393a42Smrg value.type = FcTypeInteger; 24202c393a42Smrg break; 24212c393a42Smrg case FcVStackMatrix: 24222c393a42Smrg value.u.m = FcMatrixCopy (vstack->u.matrix); 24232c393a42Smrg if (value.u.m) 24242c393a42Smrg value.type = FcTypeMatrix; 24252c393a42Smrg break; 24262c393a42Smrg case FcVStackBool: 2427a6844aabSmrg value.u.b = vstack->u.bool_; 24282c393a42Smrg value.type = FcTypeBool; 24292c393a42Smrg break; 2430ca08ab68Smrg case FcVStackCharSet: 2431ca08ab68Smrg value.u.c = FcCharSetCopy (vstack->u.charset); 2432ca08ab68Smrg if (value.u.c) 2433ca08ab68Smrg value.type = FcTypeCharSet; 2434ca08ab68Smrg break; 2435ca08ab68Smrg case FcVStackLangSet: 2436ca08ab68Smrg value.u.l = FcLangSetCopy (vstack->u.langset); 2437ca08ab68Smrg if (value.u.l) 2438ca08ab68Smrg value.type = FcTypeLangSet; 2439ca08ab68Smrg break; 24402c393a42Smrg default: 2441ca08ab68Smrg FcConfigMessage (parse, FcSevereWarning, "unknown pattern element %d", 24422c393a42Smrg vstack->tag); 24432c393a42Smrg break; 24442c393a42Smrg } 2445a6844aabSmrg FcVStackPopAndDestroy (parse); 2446ca08ab68Smrg 24472c393a42Smrg return value; 24482c393a42Smrg} 24492c393a42Smrg 24502c393a42Smrgstatic void 24512c393a42SmrgFcParsePatelt (FcConfigParse *parse) 24522c393a42Smrg{ 24532c393a42Smrg FcValue value; 24542c393a42Smrg FcPattern *pattern = FcPatternCreate (); 24552c393a42Smrg const char *name; 24562c393a42Smrg 24572c393a42Smrg if (!pattern) 24582c393a42Smrg { 24592c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 24602c393a42Smrg return; 24612c393a42Smrg } 24622c393a42Smrg 24632c393a42Smrg name = (char *) FcConfigGetAttribute (parse, "name"); 24642c393a42Smrg if (!name) 24652c393a42Smrg { 24662c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "missing pattern element name"); 24672c393a42Smrg FcPatternDestroy (pattern); 24682c393a42Smrg return; 24692c393a42Smrg } 2470ca08ab68Smrg 24712c393a42Smrg for (;;) 24722c393a42Smrg { 24732c393a42Smrg value = FcPopValue (parse); 24742c393a42Smrg if (value.type == FcTypeVoid) 24752c393a42Smrg break; 24762c393a42Smrg if (!FcPatternAdd (pattern, name, value, FcTrue)) 24772c393a42Smrg { 24782c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 2479a6844aabSmrg FcValueDestroy(value); 24802c393a42Smrg break; 24812c393a42Smrg } 2482a6844aabSmrg FcValueDestroy(value); 24832c393a42Smrg } 24842c393a42Smrg 24852c393a42Smrg FcVStackPushPattern (parse, pattern); 24862c393a42Smrg} 24872c393a42Smrg 24882c393a42Smrgstatic void 24892c393a42SmrgFcParsePattern (FcConfigParse *parse) 24902c393a42Smrg{ 24912c393a42Smrg FcVStack *vstack; 24922c393a42Smrg FcPattern *pattern = FcPatternCreate (); 24932c393a42Smrg 24942c393a42Smrg if (!pattern) 24952c393a42Smrg { 24962c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 24972c393a42Smrg return; 24982c393a42Smrg } 24992c393a42Smrg 2500a6844aabSmrg while ((vstack = FcVStackPeek (parse))) 25012c393a42Smrg { 25022c393a42Smrg switch (vstack->tag) { 25032c393a42Smrg case FcVStackPattern: 25042c393a42Smrg if (!FcPatternAppend (pattern, vstack->u.pattern)) 25052c393a42Smrg { 25062c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 25072c393a42Smrg FcPatternDestroy (pattern); 25082c393a42Smrg return; 25092c393a42Smrg } 25102c393a42Smrg break; 25112c393a42Smrg default: 25122c393a42Smrg FcConfigMessage (parse, FcSevereWarning, "unknown pattern element"); 25132c393a42Smrg break; 25142c393a42Smrg } 2515a6844aabSmrg FcVStackPopAndDestroy (parse); 25162c393a42Smrg } 25172c393a42Smrg 25182c393a42Smrg FcVStackPushPattern (parse, pattern); 25192c393a42Smrg} 25202c393a42Smrg 25212c393a42Smrgstatic void 25222c393a42SmrgFcEndElement(void *userData, const XML_Char *name) 25232c393a42Smrg{ 25242c393a42Smrg FcConfigParse *parse = userData; 25252c393a42Smrg FcChar8 *data; 2526a6844aabSmrg 25272c393a42Smrg if (!parse->pstack) 25282c393a42Smrg return; 25292c393a42Smrg switch (parse->pstack->element) { 25302c393a42Smrg case FcElementNone: 25312c393a42Smrg break; 25322c393a42Smrg case FcElementFontconfig: 25332c393a42Smrg break; 25342c393a42Smrg case FcElementDir: 2535ca08ab68Smrg FcParseDir (parse); 25362c393a42Smrg break; 25372c393a42Smrg case FcElementCacheDir: 2538ca08ab68Smrg FcParseCacheDir (parse); 25392c393a42Smrg break; 25402c393a42Smrg case FcElementCache: 2541a6844aabSmrg data = FcStrBufDoneStatic (&parse->pstack->str); 25422c393a42Smrg if (!data) 25432c393a42Smrg { 25442c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 25452c393a42Smrg break; 25462c393a42Smrg } 25472c393a42Smrg /* discard this data; no longer used */ 2548a6844aabSmrg FcStrBufDestroy (&parse->pstack->str); 25492c393a42Smrg break; 25502c393a42Smrg case FcElementInclude: 25512c393a42Smrg FcParseInclude (parse); 25522c393a42Smrg break; 25532c393a42Smrg case FcElementConfig: 25542c393a42Smrg break; 25552c393a42Smrg case FcElementMatch: 25562c393a42Smrg FcParseMatch (parse); 25572c393a42Smrg break; 25582c393a42Smrg case FcElementAlias: 25592c393a42Smrg FcParseAlias (parse); 25602c393a42Smrg break; 25612c393a42Smrg 25622c393a42Smrg case FcElementBlank: 25632c393a42Smrg FcParseBlank (parse); 25642c393a42Smrg break; 25652c393a42Smrg case FcElementRescan: 25662c393a42Smrg FcParseRescan (parse); 25672c393a42Smrg break; 25682c393a42Smrg 25692c393a42Smrg case FcElementPrefer: 25702c393a42Smrg FcParseFamilies (parse, FcVStackPrefer); 25712c393a42Smrg break; 25722c393a42Smrg case FcElementAccept: 25732c393a42Smrg FcParseFamilies (parse, FcVStackAccept); 25742c393a42Smrg break; 25752c393a42Smrg case FcElementDefault: 25762c393a42Smrg FcParseFamilies (parse, FcVStackDefault); 25772c393a42Smrg break; 25782c393a42Smrg case FcElementFamily: 25792c393a42Smrg FcParseFamily (parse); 25802c393a42Smrg break; 25812c393a42Smrg 25822c393a42Smrg case FcElementTest: 25832c393a42Smrg FcParseTest (parse); 25842c393a42Smrg break; 25852c393a42Smrg case FcElementEdit: 25862c393a42Smrg FcParseEdit (parse); 25872c393a42Smrg break; 25882c393a42Smrg 25892c393a42Smrg case FcElementInt: 25902c393a42Smrg FcParseInt (parse); 25912c393a42Smrg break; 25922c393a42Smrg case FcElementDouble: 25932c393a42Smrg FcParseDouble (parse); 25942c393a42Smrg break; 25952c393a42Smrg case FcElementString: 25962c393a42Smrg FcParseString (parse, FcVStackString); 25972c393a42Smrg break; 25982c393a42Smrg case FcElementMatrix: 25992c393a42Smrg FcParseMatrix (parse); 26002c393a42Smrg break; 2601ca08ab68Smrg case FcElementRange: 2602ca08ab68Smrg FcParseRange (parse); 2603ca08ab68Smrg break; 26042c393a42Smrg case FcElementBool: 26052c393a42Smrg FcParseBool (parse); 26062c393a42Smrg break; 2607ca08ab68Smrg case FcElementCharSet: 2608ca08ab68Smrg FcParseCharSet (parse); 2609ca08ab68Smrg break; 2610ca08ab68Smrg case FcElementLangSet: 2611ca08ab68Smrg FcParseLangSet (parse); 26122c393a42Smrg break; 26132c393a42Smrg case FcElementSelectfont: 26142c393a42Smrg break; 26152c393a42Smrg case FcElementAcceptfont: 26162c393a42Smrg case FcElementRejectfont: 26172c393a42Smrg FcParseAcceptRejectFont (parse, parse->pstack->element); 26182c393a42Smrg break; 26192c393a42Smrg case FcElementGlob: 26202c393a42Smrg FcParseString (parse, FcVStackGlob); 26212c393a42Smrg break; 26222c393a42Smrg case FcElementPattern: 26232c393a42Smrg FcParsePattern (parse); 26242c393a42Smrg break; 26252c393a42Smrg case FcElementPatelt: 26262c393a42Smrg FcParsePatelt (parse); 26272c393a42Smrg break; 26282c393a42Smrg case FcElementName: 26292c393a42Smrg FcParseString (parse, FcVStackField); 26302c393a42Smrg break; 26312c393a42Smrg case FcElementConst: 26322c393a42Smrg FcParseString (parse, FcVStackConstant); 26332c393a42Smrg break; 26342c393a42Smrg case FcElementOr: 26352c393a42Smrg FcParseBinary (parse, FcOpOr); 26362c393a42Smrg break; 26372c393a42Smrg case FcElementAnd: 26382c393a42Smrg FcParseBinary (parse, FcOpAnd); 26392c393a42Smrg break; 26402c393a42Smrg case FcElementEq: 26412c393a42Smrg FcParseBinary (parse, FcOpEqual); 26422c393a42Smrg break; 26432c393a42Smrg case FcElementNotEq: 26442c393a42Smrg FcParseBinary (parse, FcOpNotEqual); 26452c393a42Smrg break; 26462c393a42Smrg case FcElementLess: 26472c393a42Smrg FcParseBinary (parse, FcOpLess); 26482c393a42Smrg break; 26492c393a42Smrg case FcElementLessEq: 26502c393a42Smrg FcParseBinary (parse, FcOpLessEqual); 26512c393a42Smrg break; 26522c393a42Smrg case FcElementMore: 26532c393a42Smrg FcParseBinary (parse, FcOpMore); 26542c393a42Smrg break; 26552c393a42Smrg case FcElementMoreEq: 26562c393a42Smrg FcParseBinary (parse, FcOpMoreEqual); 26572c393a42Smrg break; 26582c393a42Smrg case FcElementContains: 26592c393a42Smrg FcParseBinary (parse, FcOpContains); 26602c393a42Smrg break; 26612c393a42Smrg case FcElementNotContains: 26622c393a42Smrg FcParseBinary (parse, FcOpNotContains); 26632c393a42Smrg break; 26642c393a42Smrg case FcElementPlus: 26652c393a42Smrg FcParseBinary (parse, FcOpPlus); 26662c393a42Smrg break; 26672c393a42Smrg case FcElementMinus: 26682c393a42Smrg FcParseBinary (parse, FcOpMinus); 26692c393a42Smrg break; 26702c393a42Smrg case FcElementTimes: 26712c393a42Smrg FcParseBinary (parse, FcOpTimes); 26722c393a42Smrg break; 26732c393a42Smrg case FcElementDivide: 26742c393a42Smrg FcParseBinary (parse, FcOpDivide); 26752c393a42Smrg break; 26762c393a42Smrg case FcElementNot: 26772c393a42Smrg FcParseUnary (parse, FcOpNot); 26782c393a42Smrg break; 26792c393a42Smrg case FcElementIf: 26802c393a42Smrg FcParseBinary (parse, FcOpQuest); 26812c393a42Smrg break; 26822c393a42Smrg case FcElementFloor: 26832c393a42Smrg FcParseUnary (parse, FcOpFloor); 26842c393a42Smrg break; 26852c393a42Smrg case FcElementCeil: 26862c393a42Smrg FcParseUnary (parse, FcOpCeil); 26872c393a42Smrg break; 26882c393a42Smrg case FcElementRound: 26892c393a42Smrg FcParseUnary (parse, FcOpRound); 26902c393a42Smrg break; 26912c393a42Smrg case FcElementTrunc: 26922c393a42Smrg FcParseUnary (parse, FcOpTrunc); 26932c393a42Smrg break; 26942c393a42Smrg case FcElementUnknown: 26952c393a42Smrg break; 26962c393a42Smrg } 26972c393a42Smrg (void) FcPStackPop (parse); 26982c393a42Smrg} 26992c393a42Smrg 27002c393a42Smrgstatic void 27012c393a42SmrgFcCharacterData (void *userData, const XML_Char *s, int len) 27022c393a42Smrg{ 27032c393a42Smrg FcConfigParse *parse = userData; 2704ca08ab68Smrg 27052c393a42Smrg if (!parse->pstack) 27062c393a42Smrg return; 27072c393a42Smrg if (!FcStrBufData (&parse->pstack->str, (FcChar8 *) s, len)) 27082c393a42Smrg FcConfigMessage (parse, FcSevereError, "out of memory"); 27092c393a42Smrg} 27102c393a42Smrg 27112c393a42Smrgstatic void 27122c393a42SmrgFcStartDoctypeDecl (void *userData, 27132c393a42Smrg const XML_Char *doctypeName, 27142c393a42Smrg const XML_Char *sysid, 27152c393a42Smrg const XML_Char *pubid, 27162c393a42Smrg int has_internal_subset) 27172c393a42Smrg{ 27182c393a42Smrg FcConfigParse *parse = userData; 27192c393a42Smrg 27202c393a42Smrg if (strcmp ((char *) doctypeName, "fontconfig") != 0) 27212c393a42Smrg FcConfigMessage (parse, FcSevereError, "invalid doctype \"%s\"", doctypeName); 27222c393a42Smrg} 27232c393a42Smrg 27242c393a42Smrg#ifdef ENABLE_LIBXML2 27252c393a42Smrg 27262c393a42Smrgstatic void 27272c393a42SmrgFcInternalSubsetDecl (void *userData, 27282c393a42Smrg const XML_Char *doctypeName, 27292c393a42Smrg const XML_Char *sysid, 27302c393a42Smrg const XML_Char *pubid) 27312c393a42Smrg{ 27322c393a42Smrg FcStartDoctypeDecl (userData, doctypeName, sysid, pubid, 1); 27332c393a42Smrg} 27342c393a42Smrg 27352c393a42Smrgstatic void 27362c393a42SmrgFcExternalSubsetDecl (void *userData, 27372c393a42Smrg const XML_Char *doctypeName, 27382c393a42Smrg const XML_Char *sysid, 27392c393a42Smrg const XML_Char *pubid) 27402c393a42Smrg{ 27412c393a42Smrg FcStartDoctypeDecl (userData, doctypeName, sysid, pubid, 0); 27422c393a42Smrg} 27432c393a42Smrg 27442c393a42Smrg#else /* ENABLE_LIBXML2 */ 27452c393a42Smrg 27462c393a42Smrgstatic void 27472c393a42SmrgFcEndDoctypeDecl (void *userData) 27482c393a42Smrg{ 27492c393a42Smrg} 27502c393a42Smrg 27512c393a42Smrg#endif /* ENABLE_LIBXML2 */ 27522c393a42Smrg 27532c393a42Smrgstatic int 27542c393a42SmrgFcSortCmpStr (const void *a, const void *b) 27552c393a42Smrg{ 27562c393a42Smrg const FcChar8 *as = *((FcChar8 **) a); 27572c393a42Smrg const FcChar8 *bs = *((FcChar8 **) b); 27582c393a42Smrg return FcStrCmp (as, bs); 27592c393a42Smrg} 27602c393a42Smrg 27612c393a42Smrgstatic FcBool 27622c393a42SmrgFcConfigParseAndLoadDir (FcConfig *config, 27632c393a42Smrg const FcChar8 *name, 27642c393a42Smrg const FcChar8 *dir, 27652c393a42Smrg FcBool complain) 27662c393a42Smrg{ 27672c393a42Smrg DIR *d; 27682c393a42Smrg struct dirent *e; 27692c393a42Smrg FcBool ret = FcTrue; 27702c393a42Smrg FcChar8 *file; 27712c393a42Smrg FcChar8 *base; 27722c393a42Smrg FcStrSet *files; 27732c393a42Smrg 27742c393a42Smrg d = opendir ((char *) dir); 27752c393a42Smrg if (!d) 27762c393a42Smrg { 27772c393a42Smrg if (complain) 27782c393a42Smrg FcConfigMessage (0, FcSevereError, "Cannot open config dir \"%s\"", 27792c393a42Smrg name); 27802c393a42Smrg ret = FcFalse; 27812c393a42Smrg goto bail0; 27822c393a42Smrg } 27832c393a42Smrg /* freed below */ 27842c393a42Smrg file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1); 27852c393a42Smrg if (!file) 27862c393a42Smrg { 27872c393a42Smrg ret = FcFalse; 27882c393a42Smrg goto bail1; 27892c393a42Smrg } 2790ca08ab68Smrg 27912c393a42Smrg strcpy ((char *) file, (char *) dir); 27922c393a42Smrg strcat ((char *) file, "/"); 27932c393a42Smrg base = file + strlen ((char *) file); 2794ca08ab68Smrg 27952c393a42Smrg files = FcStrSetCreate (); 27962c393a42Smrg if (!files) 27972c393a42Smrg { 27982c393a42Smrg ret = FcFalse; 27992c393a42Smrg goto bail2; 28002c393a42Smrg } 2801ca08ab68Smrg 28022c393a42Smrg if (FcDebug () & FC_DBG_CONFIG) 28032c393a42Smrg printf ("\tScanning config dir %s\n", dir); 28042c393a42Smrg 28052c393a42Smrg while (ret && (e = readdir (d))) 28062c393a42Smrg { 28072c393a42Smrg int d_len; 28082c393a42Smrg#define TAIL ".conf" 28092c393a42Smrg#define TAIL_LEN 5 28102c393a42Smrg /* 28112c393a42Smrg * Add all files of the form [0-9]*.conf 28122c393a42Smrg */ 28132c393a42Smrg if ('0' <= e->d_name[0] && e->d_name[0] <= '9' && 28142c393a42Smrg (d_len = strlen (e->d_name)) < FC_MAX_FILE_LEN && 28152c393a42Smrg d_len > TAIL_LEN && 28162c393a42Smrg strcmp (e->d_name + d_len - TAIL_LEN, TAIL) == 0) 28172c393a42Smrg { 28182c393a42Smrg strcpy ((char *) base, (char *) e->d_name); 28192c393a42Smrg if (!FcStrSetAdd (files, file)) 28202c393a42Smrg { 28212c393a42Smrg ret = FcFalse; 28222c393a42Smrg goto bail3; 28232c393a42Smrg } 28242c393a42Smrg } 28252c393a42Smrg } 28262c393a42Smrg if (ret) 28272c393a42Smrg { 28282c393a42Smrg int i; 2829ca08ab68Smrg qsort (files->strs, files->num, sizeof (FcChar8 *), 28302c393a42Smrg (int (*)(const void *, const void *)) FcSortCmpStr); 28312c393a42Smrg for (i = 0; ret && i < files->num; i++) 28322c393a42Smrg ret = FcConfigParseAndLoad (config, files->strs[i], complain); 28332c393a42Smrg } 28342c393a42Smrgbail3: 28352c393a42Smrg FcStrSetDestroy (files); 28362c393a42Smrgbail2: 28372c393a42Smrg free (file); 28382c393a42Smrgbail1: 28392c393a42Smrg closedir (d); 28402c393a42Smrgbail0: 28412c393a42Smrg return ret || !complain; 28422c393a42Smrg} 28432c393a42Smrg 2844ca08ab68Smrg#ifdef _WIN32 2845ca08ab68SmrgpfnGetSystemWindowsDirectory pGetSystemWindowsDirectory = NULL; 2846ca08ab68SmrgpfnSHGetFolderPathA pSHGetFolderPathA = NULL; 2847ca08ab68Smrg#endif 2848ca08ab68Smrg 28492c393a42SmrgFcBool 28502c393a42SmrgFcConfigParseAndLoad (FcConfig *config, 28512c393a42Smrg const FcChar8 *name, 28522c393a42Smrg FcBool complain) 28532c393a42Smrg{ 28542c393a42Smrg 28552c393a42Smrg XML_Parser p; 28562c393a42Smrg FcChar8 *filename; 28572c393a42Smrg int fd; 28582c393a42Smrg int len; 28592c393a42Smrg FcConfigParse parse; 28602c393a42Smrg FcBool error = FcTrue; 2861ca08ab68Smrg 28622c393a42Smrg#ifdef ENABLE_LIBXML2 28632c393a42Smrg xmlSAXHandler sax; 28642c393a42Smrg char buf[BUFSIZ]; 28652c393a42Smrg#else 28662c393a42Smrg void *buf; 28672c393a42Smrg#endif 2868ca08ab68Smrg 2869ca08ab68Smrg#ifdef _WIN32 2870ca08ab68Smrg if (!pGetSystemWindowsDirectory) 2871ca08ab68Smrg { 2872ca08ab68Smrg HMODULE hk32 = GetModuleHandleA("kernel32.dll"); 2873ca08ab68Smrg if (!(pGetSystemWindowsDirectory = (pfnGetSystemWindowsDirectory) GetProcAddress(hk32, "GetSystemWindowsDirectoryA"))) 2874ca08ab68Smrg pGetSystemWindowsDirectory = (pfnGetSystemWindowsDirectory) GetWindowsDirectory; 2875ca08ab68Smrg } 2876ca08ab68Smrg if (!pSHGetFolderPathA) 2877ca08ab68Smrg { 2878ca08ab68Smrg HMODULE hSh = LoadLibraryA("shfolder.dll"); 2879ca08ab68Smrg /* the check is done later, because there is no provided fallback */ 2880ca08ab68Smrg if (hSh) 2881ca08ab68Smrg pSHGetFolderPathA = (pfnSHGetFolderPathA) GetProcAddress(hSh, "SHGetFolderPathA"); 2882ca08ab68Smrg } 2883ca08ab68Smrg#endif 2884ca08ab68Smrg 28852c393a42Smrg filename = FcConfigFilename (name); 28862c393a42Smrg if (!filename) 28872c393a42Smrg goto bail0; 2888ca08ab68Smrg 28892c393a42Smrg if (FcStrSetMember (config->configFiles, filename)) 28902c393a42Smrg { 28912c393a42Smrg FcStrFree (filename); 28922c393a42Smrg return FcTrue; 28932c393a42Smrg } 28942c393a42Smrg 28952c393a42Smrg if (!FcStrSetAdd (config->configFiles, filename)) 28962c393a42Smrg { 28972c393a42Smrg FcStrFree (filename); 28982c393a42Smrg goto bail0; 28992c393a42Smrg } 29002c393a42Smrg 29012c393a42Smrg if (FcFileIsDir (filename)) 29022c393a42Smrg { 29032c393a42Smrg FcBool ret = FcConfigParseAndLoadDir (config, name, filename, complain); 29042c393a42Smrg FcStrFree (filename); 29052c393a42Smrg return ret; 29062c393a42Smrg } 29072c393a42Smrg 29082c393a42Smrg if (FcDebug () & FC_DBG_CONFIG) 29092c393a42Smrg printf ("\tLoading config file %s\n", filename); 29102c393a42Smrg 29112c393a42Smrg fd = open ((char *) filename, O_RDONLY); 2912ca08ab68Smrg if (fd == -1) { 29132c393a42Smrg FcStrFree (filename); 29142c393a42Smrg goto bail0; 29152c393a42Smrg } 2916ca08ab68Smrg 29172c393a42Smrg#ifdef ENABLE_LIBXML2 29182c393a42Smrg memset(&sax, 0, sizeof(sax)); 29192c393a42Smrg 29202c393a42Smrg sax.internalSubset = FcInternalSubsetDecl; 29212c393a42Smrg sax.externalSubset = FcExternalSubsetDecl; 29222c393a42Smrg sax.startElement = FcStartElement; 29232c393a42Smrg sax.endElement = FcEndElement; 29242c393a42Smrg sax.characters = FcCharacterData; 29252c393a42Smrg 29262c393a42Smrg p = xmlCreatePushParserCtxt (&sax, &parse, NULL, 0, (const char *) filename); 29272c393a42Smrg#else 29282c393a42Smrg p = XML_ParserCreate ("UTF-8"); 29292c393a42Smrg#endif 29302c393a42Smrg FcStrFree (filename); 29312c393a42Smrg 29322c393a42Smrg if (!p) 29332c393a42Smrg goto bail1; 29342c393a42Smrg 29352c393a42Smrg if (!FcConfigInit (&parse, name, config, p)) 29362c393a42Smrg goto bail2; 29372c393a42Smrg 29382c393a42Smrg#ifndef ENABLE_LIBXML2 29392c393a42Smrg 29402c393a42Smrg XML_SetUserData (p, &parse); 2941ca08ab68Smrg 29422c393a42Smrg XML_SetDoctypeDeclHandler (p, FcStartDoctypeDecl, FcEndDoctypeDecl); 29432c393a42Smrg XML_SetElementHandler (p, FcStartElement, FcEndElement); 29442c393a42Smrg XML_SetCharacterDataHandler (p, FcCharacterData); 29452c393a42Smrg 29462c393a42Smrg#endif /* ENABLE_LIBXML2 */ 29472c393a42Smrg 29482c393a42Smrg do { 29492c393a42Smrg#ifndef ENABLE_LIBXML2 29502c393a42Smrg buf = XML_GetBuffer (p, BUFSIZ); 29512c393a42Smrg if (!buf) 29522c393a42Smrg { 29532c393a42Smrg FcConfigMessage (&parse, FcSevereError, "cannot get parse buffer"); 29542c393a42Smrg goto bail3; 29552c393a42Smrg } 29562c393a42Smrg#endif 29572c393a42Smrg len = read (fd, buf, BUFSIZ); 29582c393a42Smrg if (len < 0) 29592c393a42Smrg { 29602c393a42Smrg FcConfigMessage (&parse, FcSevereError, "failed reading config file"); 29612c393a42Smrg goto bail3; 29622c393a42Smrg } 29632c393a42Smrg 29642c393a42Smrg#ifdef ENABLE_LIBXML2 29652c393a42Smrg if (xmlParseChunk (p, buf, len, len == 0)) 29662c393a42Smrg#else 29672c393a42Smrg if (!XML_ParseBuffer (p, len, len == 0)) 29682c393a42Smrg#endif 29692c393a42Smrg { 2970ca08ab68Smrg FcConfigMessage (&parse, FcSevereError, "%s", 29712c393a42Smrg XML_ErrorString (XML_GetErrorCode (p))); 29722c393a42Smrg goto bail3; 29732c393a42Smrg } 29742c393a42Smrg } while (len != 0); 29752c393a42Smrg error = parse.error; 29762c393a42Smrgbail3: 29772c393a42Smrg FcConfigCleanup (&parse); 29782c393a42Smrgbail2: 29792c393a42Smrg XML_ParserFree (p); 29802c393a42Smrgbail1: 29812c393a42Smrg close (fd); 29822c393a42Smrg fd = -1; 29832c393a42Smrgbail0: 29842c393a42Smrg if (error && complain) 29852c393a42Smrg { 29862c393a42Smrg if (name) 29872c393a42Smrg FcConfigMessage (0, FcSevereError, "Cannot load config file \"%s\"", name); 29882c393a42Smrg else 29892c393a42Smrg FcConfigMessage (0, FcSevereError, "Cannot load default config file"); 29902c393a42Smrg return FcFalse; 29912c393a42Smrg } 29922c393a42Smrg return FcTrue; 29932c393a42Smrg} 29942c393a42Smrg#define __fcxml__ 29952c393a42Smrg#include "fcaliastail.h" 29962c393a42Smrg#undef __fcxml__ 2997