/*
- * $RCSId: xc/lib/fontconfig/src/fcxml.c,v 1.21 2002/08/22 18:53:22 keithp Exp $
+ * fontconfig/src/fcxml.c
*
* Copyright © 2002 Keith Packard
*
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
-#include <stdarg.h>
#include "fcint.h"
+#include <fcntl.h>
+#include <stdarg.h>
#include <dirent.h>
+#ifdef ENABLE_LIBXML2
+
+#include <libxml/parser.h>
+
+#define XML_Char xmlChar
+#define XML_Parser xmlParserCtxtPtr
+#define XML_ParserFree xmlFreeParserCtxt
+#define XML_GetCurrentLineNumber xmlSAX2GetLineNumber
+#define XML_GetErrorCode xmlCtxtGetLastError
+#define XML_ErrorString(Error) (Error)->message
+
+#else /* ENABLE_LIBXML2 */
+
#ifndef HAVE_XMLPARSE_H
#define HAVE_XMLPARSE_H 0
#endif
#include <expat.h>
#endif
+#endif /* ENABLE_LIBXML2 */
+
#ifdef _WIN32
+#define _WIN32_WINNT 0x0500
#define STRICT
#include <windows.h>
#undef STRICT
+#include <mbstring.h>
#endif
-FcTest *
-FcTestCreate (FcMatchKind kind,
- FcQual qual,
- const FcChar8 *field,
- FcOp compare,
- FcExpr *expr)
-{
- FcTest *test = (FcTest *) malloc (sizeof (FcTest));
-
- if (test)
- {
- FcMemAlloc (FC_MEM_TEST, sizeof (FcTest));
- test->next = 0;
- test->kind = kind;
- test->qual = qual;
- test->field = (char *) FcStrCopy (field);
- test->op = compare;
- test->expr = expr;
- }
- return test;
-}
+static void
+FcExprDestroy (FcExpr *e);
void
FcTestDestroy (FcTest *test)
if (test->next)
FcTestDestroy (test->next);
FcExprDestroy (test->expr);
- FcStrFree ((FcChar8 *) test->field);
FcMemFree (FC_MEM_TEST, sizeof (FcTest));
free (test);
}
-FcExpr *
-FcExprCreateInteger (int i)
+static FcExpr *
+FcExprCreateInteger (FcConfig *config, int i)
{
- FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
-
+ FcExpr *e = FcConfigAllocExpr (config);
if (e)
{
- FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpInteger;
e->u.ival = i;
}
return e;
}
-FcExpr *
-FcExprCreateDouble (double d)
+static FcExpr *
+FcExprCreateDouble (FcConfig *config, double d)
{
- FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
-
+ FcExpr *e = FcConfigAllocExpr (config);
if (e)
{
- FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpDouble;
e->u.dval = d;
}
return e;
}
-FcExpr *
-FcExprCreateString (const FcChar8 *s)
+static FcExpr *
+FcExprCreateString (FcConfig *config, const FcChar8 *s)
{
- FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
-
+ FcExpr *e = FcConfigAllocExpr (config);
if (e)
{
- FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpString;
- e->u.sval = FcStrCopy (s);
+ e->u.sval = FcStrStaticName (s);
}
return e;
}
-FcExpr *
-FcExprCreateMatrix (const FcMatrix *m)
+static FcExpr *
+FcExprCreateMatrix (FcConfig *config, const FcMatrix *m)
{
- FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
-
+ FcExpr *e = FcConfigAllocExpr (config);
if (e)
{
- FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpMatrix;
e->u.mval = FcMatrixCopy (m);
}
return e;
}
-FcExpr *
-FcExprCreateBool (FcBool b)
+static FcExpr *
+FcExprCreateBool (FcConfig *config, FcBool b)
{
- FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
-
+ FcExpr *e = FcConfigAllocExpr (config);
if (e)
{
- FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpBool;
e->u.bval = b;
}
return e;
}
-FcExpr *
-FcExprCreateNil (void)
-{
- FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
-
- if (e)
- {
- FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
- e->op = FcOpNil;
- }
- return e;
-}
-
-FcExpr *
-FcExprCreateField (const char *field)
+static FcExpr *
+FcExprCreateField (FcConfig *config, const char *field)
{
- FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
-
+ FcExpr *e = FcConfigAllocExpr (config);
if (e)
{
- FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpField;
- e->u.field = (char *) FcStrCopy ((FcChar8 *) field);
+ e->u.object = FcObjectFromName (field);
}
return e;
}
-FcExpr *
-FcExprCreateConst (const FcChar8 *constant)
+static FcExpr *
+FcExprCreateConst (FcConfig *config, const FcChar8 *constant)
{
- FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
-
+ FcExpr *e = FcConfigAllocExpr (config);
if (e)
{
- FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpConst;
- e->u.constant = FcStrCopy (constant);
+ e->u.constant = FcStrStaticName (constant);
}
return e;
}
-FcExpr *
-FcExprCreateOp (FcExpr *left, FcOp op, FcExpr *right)
+static FcExpr *
+FcExprCreateOp (FcConfig *config, FcExpr *left, FcOp op, FcExpr *right)
{
- FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
-
+ FcExpr *e = FcConfigAllocExpr (config);
if (e)
{
- FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = op;
e->u.tree.left = left;
e->u.tree.right = right;
return e;
}
-void
+static void
FcExprDestroy (FcExpr *e)
{
if (!e)
case FcOpDouble:
break;
case FcOpString:
- FcStrFree (e->u.sval);
break;
case FcOpMatrix:
FcMatrixFree (e->u.mval);
case FcOpBool:
break;
case FcOpField:
- FcStrFree ((FcChar8 *) e->u.field);
break;
case FcOpConst:
- FcStrFree (e->u.constant);
break;
case FcOpAssign:
case FcOpAssignReplace:
case FcOpInvalid:
break;
}
- FcMemFree (FC_MEM_EXPR, sizeof (FcExpr));
- free (e);
-}
-FcEdit *
-FcEditCreate (const char *field, FcOp op, FcExpr *expr, FcValueBinding binding)
-{
- FcEdit *e = (FcEdit *) malloc (sizeof (FcEdit));
-
- if (e)
- {
- e->next = 0;
- e->field = field; /* already saved in grammar */
- e->op = op;
- e->expr = expr;
- e->binding = binding;
- }
- return e;
+ e->op = FcOpNil;
}
void
{
if (e->next)
FcEditDestroy (e->next);
- FcStrFree ((FcChar8 *) e->field);
if (e->expr)
FcExprDestroy (e->expr);
free (e);
}
-char *
-FcConfigSaveField (const char *field)
-{
- return (char *) FcStrCopy ((FcChar8 *) field);
-}
-
typedef enum _FcElement {
FcElementNone,
FcElementFontconfig,
FcElementDir,
+ FcElementCacheDir,
FcElementCache,
FcElementInclude,
FcElementConfig,
FcElementUnknown
} FcElement;
+static const struct {
+ const char name[16];
+ FcElement element;
+} fcElementMap[] = {
+ { "fontconfig", FcElementFontconfig },
+ { "dir", FcElementDir },
+ { "cachedir", FcElementCacheDir },
+ { "cache", FcElementCache },
+ { "include", FcElementInclude },
+ { "config", FcElementConfig },
+ { "match", FcElementMatch },
+ { "alias", FcElementAlias },
+
+ { "blank", FcElementBlank },
+ { "rescan", FcElementRescan },
+
+ { "prefer", FcElementPrefer },
+ { "accept", FcElementAccept },
+ { "default", FcElementDefault },
+ { "family", FcElementFamily },
+
+ { "selectfont", FcElementSelectfont },
+ { "acceptfont", FcElementAcceptfont },
+ { "rejectfont", FcElementRejectfont },
+ { "glob", FcElementGlob },
+ { "pattern", FcElementPattern },
+ { "patelt", FcElementPatelt },
+
+ { "test", FcElementTest },
+ { "edit", FcElementEdit },
+ { "int", FcElementInt },
+ { "double", FcElementDouble },
+ { "string", FcElementString },
+ { "matrix", FcElementMatrix },
+ { "bool", FcElementBool },
+ { "charset", FcElementCharset },
+ { "name", FcElementName },
+ { "const", FcElementConst },
+ { "or", FcElementOr },
+ { "and", FcElementAnd },
+ { "eq", FcElementEq },
+ { "not_eq", FcElementNotEq },
+ { "less", FcElementLess },
+ { "less_eq", FcElementLessEq },
+ { "more", FcElementMore },
+ { "more_eq", FcElementMoreEq },
+ { "contains", FcElementContains },
+ { "not_contains", FcElementNotContains },
+ { "plus", FcElementPlus },
+ { "minus", FcElementMinus },
+ { "times", FcElementTimes },
+ { "divide", FcElementDivide },
+ { "not", FcElementNot },
+ { "if", FcElementIf },
+ { "floor", FcElementFloor },
+ { "ceil", FcElementCeil },
+ { "round", FcElementRound },
+ { "trunc", FcElementTrunc },
+};
+#define NUM_ELEMENT_MAPS (int) (sizeof fcElementMap / sizeof fcElementMap[0])
+
static FcElement
FcElementMap (const XML_Char *name)
{
- static struct {
- char *name;
- FcElement element;
- } fcElementMap[] = {
- { "fontconfig", FcElementFontconfig },
- { "dir", FcElementDir },
- { "cache", FcElementCache },
- { "include", FcElementInclude },
- { "config", FcElementConfig },
- { "match", FcElementMatch },
- { "alias", FcElementAlias },
-
- { "blank", FcElementBlank },
- { "rescan", FcElementRescan },
-
- { "prefer", FcElementPrefer },
- { "accept", FcElementAccept },
- { "default", FcElementDefault },
- { "family", FcElementFamily },
-
- { "selectfont", FcElementSelectfont },
- { "acceptfont", FcElementAcceptfont },
- { "rejectfont", FcElementRejectfont },
- { "glob", FcElementGlob },
- { "pattern", FcElementPattern },
- { "patelt", FcElementPatelt },
-
- { "test", FcElementTest },
- { "edit", FcElementEdit },
- { "int", FcElementInt },
- { "double", FcElementDouble },
- { "string", FcElementString },
- { "matrix", FcElementMatrix },
- { "bool", FcElementBool },
- { "charset", FcElementCharset },
- { "name", FcElementName },
- { "const", FcElementConst },
- { "or", FcElementOr },
- { "and", FcElementAnd },
- { "eq", FcElementEq },
- { "not_eq", FcElementNotEq },
- { "less", FcElementLess },
- { "less_eq", FcElementLessEq },
- { "more", FcElementMore },
- { "more_eq", FcElementMoreEq },
- { "contains", FcElementContains },
- { "not_contains",FcElementNotContains },
- { "plus", FcElementPlus },
- { "minus", FcElementMinus },
- { "times", FcElementTimes },
- { "divide", FcElementDivide },
- { "not", FcElementNot },
- { "if", FcElementIf },
- { "floor", FcElementFloor },
- { "ceil", FcElementCeil },
- { "round", FcElementRound },
- { "trunc", FcElementTrunc },
-
- { 0, 0 }
- };
int i;
- for (i = 0; fcElementMap[i].name; i++)
+ for (i = 0; i < NUM_ELEMENT_MAPS; i++)
if (!strcmp ((char *) name, fcElementMap[i].name))
return fcElementMap[i].element;
return FcElementUnknown;
FcElement element;
FcChar8 **attr;
FcStrBuf str;
+ FcChar8 *attr_buf_static[16];
} FcPStack;
typedef enum _FcVStackTag {
int integer;
double _double;
FcMatrix *matrix;
- FcBool bool;
+ FcBool bool_;
FcTest *test;
FcQual qual;
const FcChar8 *name;
FcConfig *config;
XML_Parser parser;
+ int pstack_static_used;
+ FcPStack pstack_static[8];
+ int vstack_static_used;
+ FcVStack vstack_static[64];
} FcConfigParse;
typedef enum _FcConfigSeverity {
} FcConfigSeverity;
static void
-FcConfigMessage (FcConfigParse *parse, FcConfigSeverity severe, char *fmt, ...)
+FcConfigMessage (FcConfigParse *parse, FcConfigSeverity severe, const char *fmt, ...)
{
- char *s = "unknown";
+ const char *s = "unknown";
va_list args;
va_start (args, fmt);
{
if (parse->name)
fprintf (stderr, "Fontconfig %s: \"%s\", line %d: ", s,
- parse->name, XML_GetCurrentLineNumber (parse->parser));
+ parse->name, (int)XML_GetCurrentLineNumber (parse->parser));
else
fprintf (stderr, "Fontconfig %s: line %d: ", s,
- XML_GetCurrentLineNumber (parse->parser));
+ (int)XML_GetCurrentLineNumber (parse->parser));
if (severe >= FcSevereError)
parse->error = FcTrue;
}
va_end (args);
}
+
+static const char *
+FcTypeName (FcType type)
+{
+ switch (type) {
+ case FcTypeVoid:
+ return "void";
+ case FcTypeInteger:
+ case FcTypeDouble:
+ return "number";
+ case FcTypeString:
+ return "string";
+ case FcTypeBool:
+ return "bool";
+ case FcTypeMatrix:
+ return "matrix";
+ case FcTypeCharSet:
+ return "charset";
+ case FcTypeFTFace:
+ return "FT_Face";
+ case FcTypeLangSet:
+ return "langset";
+ default:
+ return "unknown";
+ }
+}
+
static void
-FcVStackPush (FcConfigParse *parse, FcVStack *vstack)
+FcTypecheckValue (FcConfigParse *parse, FcType value, FcType type)
{
- vstack->prev = parse->vstack;
- vstack->pstack = parse->pstack ? parse->pstack->prev : 0;
- parse->vstack = vstack;
+ if (value == FcTypeInteger)
+ value = FcTypeDouble;
+ if (type == FcTypeInteger)
+ type = FcTypeDouble;
+ if (value != type)
+ {
+ if ((value == FcTypeLangSet && type == FcTypeString) ||
+ (value == FcTypeString && type == FcTypeLangSet))
+ return;
+ if (type == (FcType) -1)
+ return;
+ FcConfigMessage (parse, FcSevereWarning, "saw %s, expected %s",
+ FcTypeName (value), FcTypeName (type));
+ }
}
-static FcVStack *
-FcVStackCreate (void)
+static void
+FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type)
{
- FcVStack *new;
+ const FcObjectType *o;
+ const FcConstant *c;
+
+ /* If parsing the expression failed, some nodes may be NULL */
+ if (!expr)
+ return;
- new = malloc (sizeof (FcVStack));
- if (!new)
- return 0;
- FcMemAlloc (FC_MEM_VSTACK, sizeof (FcVStack));
- new->tag = FcVStackNone;
- new->prev = 0;
- return new;
+ switch (expr->op) {
+ case FcOpInteger:
+ case FcOpDouble:
+ FcTypecheckValue (parse, FcTypeDouble, type);
+ break;
+ case FcOpString:
+ FcTypecheckValue (parse, FcTypeString, type);
+ break;
+ case FcOpMatrix:
+ FcTypecheckValue (parse, FcTypeMatrix, type);
+ break;
+ case FcOpBool:
+ FcTypecheckValue (parse, FcTypeBool, type);
+ break;
+ case FcOpCharSet:
+ FcTypecheckValue (parse, FcTypeCharSet, type);
+ break;
+ case FcOpNil:
+ break;
+ case FcOpField:
+ o = FcNameGetObjectType (FcObjectName (expr->u.object));
+ if (o)
+ FcTypecheckValue (parse, o->type, type);
+ break;
+ case FcOpConst:
+ c = FcNameGetConstant (expr->u.constant);
+ if (c)
+ {
+ o = FcNameGetObjectType (c->object);
+ if (o)
+ FcTypecheckValue (parse, o->type, type);
+ }
+ else
+ FcConfigMessage (parse, FcSevereWarning,
+ "invalid constant used : %s",
+ expr->u.constant);
+ break;
+ case FcOpQuest:
+ FcTypecheckExpr (parse, expr->u.tree.left, FcTypeBool);
+ FcTypecheckExpr (parse, expr->u.tree.right->u.tree.left, type);
+ FcTypecheckExpr (parse, expr->u.tree.right->u.tree.right, type);
+ break;
+ case FcOpAssign:
+ case FcOpAssignReplace:
+ break;
+ case FcOpEqual:
+ case FcOpNotEqual:
+ case FcOpLess:
+ case FcOpLessEqual:
+ case FcOpMore:
+ case FcOpMoreEqual:
+ case FcOpContains:
+ case FcOpNotContains:
+ case FcOpListing:
+ FcTypecheckValue (parse, FcTypeBool, type);
+ break;
+ case FcOpComma:
+ case FcOpOr:
+ case FcOpAnd:
+ case FcOpPlus:
+ case FcOpMinus:
+ case FcOpTimes:
+ case FcOpDivide:
+ FcTypecheckExpr (parse, expr->u.tree.left, type);
+ FcTypecheckExpr (parse, expr->u.tree.right, type);
+ break;
+ case FcOpNot:
+ FcTypecheckValue (parse, FcTypeBool, type);
+ FcTypecheckExpr (parse, expr->u.tree.left, FcTypeBool);
+ break;
+ case FcOpFloor:
+ case FcOpCeil:
+ case FcOpRound:
+ case FcOpTrunc:
+ FcTypecheckValue (parse, FcTypeDouble, type);
+ FcTypecheckExpr (parse, expr->u.tree.left, FcTypeDouble);
+ break;
+ default:
+ break;
+ }
}
-static void
-FcVStackDestroy (FcVStack *vstack)
+static FcTest *
+FcTestCreate (FcConfigParse *parse,
+ FcMatchKind kind,
+ FcQual qual,
+ const FcChar8 *field,
+ FcOp compare,
+ FcExpr *expr)
{
- FcVStack *prev;
+ FcTest *test = (FcTest *) malloc (sizeof (FcTest));
- for (; vstack; vstack = prev)
+ if (test)
{
- prev = vstack->prev;
- switch (vstack->tag) {
- case FcVStackNone:
- break;
- case FcVStackString:
- case FcVStackFamily:
- case FcVStackField:
- case FcVStackConstant:
- case FcVStackGlob:
- FcStrFree (vstack->u.string);
- break;
- case FcVStackPattern:
- FcPatternDestroy (vstack->u.pattern);
- break;
- case FcVStackInteger:
- case FcVStackDouble:
- break;
- case FcVStackMatrix:
- FcMatrixFree (vstack->u.matrix);
- break;
- case FcVStackBool:
- break;
- case FcVStackTest:
- FcTestDestroy (vstack->u.test);
- break;
- case FcVStackExpr:
- case FcVStackPrefer:
- case FcVStackAccept:
- case FcVStackDefault:
- FcExprDestroy (vstack->u.expr);
- break;
- case FcVStackEdit:
- FcEditDestroy (vstack->u.edit);
- break;
- }
- FcMemFree (FC_MEM_VSTACK, sizeof (FcVStack));
- free (vstack);
+ const FcObjectType *o;
+
+ FcMemAlloc (FC_MEM_TEST, sizeof (FcTest));
+ test->next = 0;
+ test->kind = kind;
+ test->qual = qual;
+ test->object = FcObjectFromName ((const char *) field);
+ test->op = compare;
+ test->expr = expr;
+ o = FcNameGetObjectType (FcObjectName (test->object));
+ if (o)
+ FcTypecheckExpr (parse, expr, o->type);
}
+ return test;
+}
+
+static FcEdit *
+FcEditCreate (FcConfigParse *parse,
+ FcObject object,
+ FcOp op,
+ FcExpr *expr,
+ FcValueBinding binding)
+{
+ FcEdit *e = (FcEdit *) malloc (sizeof (FcEdit));
+
+ if (e)
+ {
+ const FcObjectType *o;
+
+ e->next = 0;
+ e->object = object;
+ e->op = op;
+ e->expr = expr;
+ e->binding = binding;
+ o = FcNameGetObjectType (FcObjectName (e->object));
+ if (o)
+ FcTypecheckExpr (parse, expr, o->type);
+ }
+ return e;
+}
+
+static FcVStack *
+FcVStackCreateAndPush (FcConfigParse *parse)
+{
+ FcVStack *new;
+
+ if (parse->vstack_static_used < sizeof (parse->vstack_static) / sizeof (parse->vstack_static[0]))
+ new = &parse->vstack_static[parse->vstack_static_used++];
+ else
+ {
+ new = malloc (sizeof (FcVStack));
+ if (!new)
+ return 0;
+ FcMemAlloc (FC_MEM_VSTACK, sizeof (FcVStack));
+ }
+ new->tag = FcVStackNone;
+ new->prev = 0;
+
+ new->prev = parse->vstack;
+ new->pstack = parse->pstack ? parse->pstack->prev : 0;
+ parse->vstack = new;
+
+ return new;
}
static FcBool
FcVStackPushString (FcConfigParse *parse, FcVStackTag tag, FcChar8 *string)
{
- FcVStack *vstack = FcVStackCreate ();
+ FcVStack *vstack = FcVStackCreateAndPush (parse);
if (!vstack)
return FcFalse;
vstack->u.string = string;
vstack->tag = tag;
- FcVStackPush (parse, vstack);
return FcTrue;
}
static FcBool
FcVStackPushInteger (FcConfigParse *parse, int integer)
{
- FcVStack *vstack = FcVStackCreate ();
+ FcVStack *vstack = FcVStackCreateAndPush (parse);
if (!vstack)
return FcFalse;
vstack->u.integer = integer;
vstack->tag = FcVStackInteger;
- FcVStackPush (parse, vstack);
return FcTrue;
}
static FcBool
FcVStackPushDouble (FcConfigParse *parse, double _double)
{
- FcVStack *vstack = FcVStackCreate ();
+ FcVStack *vstack = FcVStackCreateAndPush (parse);
if (!vstack)
return FcFalse;
vstack->u._double = _double;
vstack->tag = FcVStackDouble;
- FcVStackPush (parse, vstack);
return FcTrue;
}
static FcBool
FcVStackPushMatrix (FcConfigParse *parse, FcMatrix *matrix)
{
- FcVStack *vstack = FcVStackCreate ();
- if (!vstack)
- return FcFalse;
+ FcVStack *vstack;
matrix = FcMatrixCopy (matrix);
if (!matrix)
- {
- FcVStackDestroy (vstack);
return FcFalse;
- }
+ vstack = FcVStackCreateAndPush (parse);
+ if (!vstack)
+ return FcFalse;
vstack->u.matrix = matrix;
vstack->tag = FcVStackMatrix;
- FcVStackPush (parse, vstack);
return FcTrue;
}
static FcBool
-FcVStackPushBool (FcConfigParse *parse, FcBool bool)
+FcVStackPushBool (FcConfigParse *parse, FcBool bool_)
{
- FcVStack *vstack = FcVStackCreate ();
+ FcVStack *vstack = FcVStackCreateAndPush (parse);
if (!vstack)
return FcFalse;
- vstack->u.bool = bool;
+ vstack->u.bool_ = bool_;
vstack->tag = FcVStackBool;
- FcVStackPush (parse, vstack);
return FcTrue;
}
static FcBool
FcVStackPushTest (FcConfigParse *parse, FcTest *test)
{
- FcVStack *vstack = FcVStackCreate ();
+ FcVStack *vstack = FcVStackCreateAndPush (parse);
if (!vstack)
return FcFalse;
vstack->u.test = test;
vstack->tag = FcVStackTest;
- FcVStackPush (parse, vstack);
return FcTrue;
}
static FcBool
FcVStackPushExpr (FcConfigParse *parse, FcVStackTag tag, FcExpr *expr)
{
- FcVStack *vstack = FcVStackCreate ();
+ FcVStack *vstack = FcVStackCreateAndPush (parse);
if (!vstack)
return FcFalse;
vstack->u.expr = expr;
vstack->tag = tag;
- FcVStackPush (parse, vstack);
return FcTrue;
}
static FcBool
FcVStackPushEdit (FcConfigParse *parse, FcEdit *edit)
{
- FcVStack *vstack = FcVStackCreate ();
+ FcVStack *vstack = FcVStackCreateAndPush (parse);
if (!vstack)
return FcFalse;
vstack->u.edit = edit;
vstack->tag = FcVStackEdit;
- FcVStackPush (parse, vstack);
return FcTrue;
}
static FcBool
FcVStackPushPattern (FcConfigParse *parse, FcPattern *pattern)
{
- FcVStack *vstack = FcVStackCreate ();
+ FcVStack *vstack = FcVStackCreateAndPush (parse);
if (!vstack)
return FcFalse;
vstack->u.pattern = pattern;
vstack->tag = FcVStackPattern;
- FcVStackPush (parse, vstack);
return FcTrue;
}
return vstack;
}
-static void
-FcVStackClear (FcConfigParse *parse)
+static FcVStack *
+FcVStackPeek (FcConfigParse *parse)
{
- while (parse->vstack && parse->vstack->pstack == parse->pstack)
- {
- FcVStack *vstack = parse->vstack;
- parse->vstack = vstack->prev;
- vstack->prev = 0;
- FcVStackDestroy (vstack);
- }
+ FcVStack *vstack = parse->vstack;
+
+ return vstack && vstack->pstack == parse->pstack ? vstack : 0;
}
-static FcVStack *
-FcVStackPop (FcConfigParse *parse)
+static void
+FcVStackPopAndDestroy (FcConfigParse *parse)
{
FcVStack *vstack = parse->vstack;
if (!vstack || vstack->pstack != parse->pstack)
- return 0;
+ return;
+
parse->vstack = vstack->prev;
- vstack->prev = 0;
- return vstack;
+
+ switch (vstack->tag) {
+ case FcVStackNone:
+ break;
+ case FcVStackFamily:
+ break;
+ case FcVStackString:
+ case FcVStackField:
+ case FcVStackConstant:
+ case FcVStackGlob:
+ FcStrFree (vstack->u.string);
+ break;
+ case FcVStackPattern:
+ FcPatternDestroy (vstack->u.pattern);
+ break;
+ case FcVStackInteger:
+ case FcVStackDouble:
+ break;
+ case FcVStackMatrix:
+ FcMatrixFree (vstack->u.matrix);
+ break;
+ case FcVStackBool:
+ break;
+ case FcVStackTest:
+ FcTestDestroy (vstack->u.test);
+ break;
+ case FcVStackExpr:
+ case FcVStackPrefer:
+ case FcVStackAccept:
+ case FcVStackDefault:
+ FcExprDestroy (vstack->u.expr);
+ break;
+ case FcVStackEdit:
+ FcEditDestroy (vstack->u.edit);
+ break;
+ }
+
+ if (vstack == &parse->vstack_static[parse->vstack_static_used - 1])
+ parse->vstack_static_used--;
+ else
+ {
+ FcMemFree (FC_MEM_VSTACK, sizeof (FcVStack));
+ free (vstack);
+ }
+}
+
+static void
+FcVStackClear (FcConfigParse *parse)
+{
+ while (FcVStackPeek (parse))
+ FcVStackPopAndDestroy (parse);
}
static int
}
static FcChar8 **
-FcConfigSaveAttr (const XML_Char **attr)
+FcConfigSaveAttr (const XML_Char **attr, FcChar8 **buf, int size_bytes)
{
- int n;
int slen;
int i;
FcChar8 **new;
return 0;
slen = 0;
for (i = 0; attr[i]; i++)
- slen += strlen (attr[i]) + 1;
- n = i;
- new = malloc ((i + 1) * sizeof (FcChar8 *) + slen);
- if (!new)
+ slen += strlen ((char *) attr[i]) + 1;
+ if (i == 0)
return 0;
- FcMemAlloc (FC_MEM_ATTR, 1); /* size is too expensive */
+ slen += (i + 1) * sizeof (FcChar8 *);
+ if (slen <= size_bytes)
+ new = buf;
+ else
+ {
+ new = malloc (slen);
+ if (!new)
+ {
+ FcConfigMessage (0, FcSevereError, "out of memory");
+ return 0;
+ }
+ FcMemAlloc (FC_MEM_ATTR, 1); /* size is too expensive */
+ }
s = (FcChar8 *) (new + (i + 1));
for (i = 0; attr[i]; i++)
{
static FcBool
FcPStackPush (FcConfigParse *parse, FcElement element, const XML_Char **attr)
{
- FcPStack *new = malloc (sizeof (FcPStack));
+ FcPStack *new;
- if (!new)
- return FcFalse;
- FcMemAlloc (FC_MEM_PSTACK, sizeof (FcPStack));
- new->prev = parse->pstack;
- new->element = element;
- if (attr)
+ if (parse->pstack_static_used < sizeof (parse->pstack_static) / sizeof (parse->pstack_static[0]))
+ new = &parse->pstack_static[parse->pstack_static_used++];
+ else
{
- new->attr = FcConfigSaveAttr (attr);
- if (!new->attr)
- FcConfigMessage (parse, FcSevereError, "out of memory");
+ new = malloc (sizeof (FcPStack));
+ if (!new)
+ return FcFalse;
+ FcMemAlloc (FC_MEM_PSTACK, sizeof (FcPStack));
}
- else
- new->attr = 0;
+
+ new->prev = parse->pstack;
+ new->element = element;
+ new->attr = FcConfigSaveAttr (attr, new->attr_buf_static, sizeof (new->attr_buf_static));
FcStrBufInit (&new->str, 0, 0);
parse->pstack = new;
return FcTrue;
old = parse->pstack;
parse->pstack = old->prev;
FcStrBufDestroy (&old->str);
- if (old->attr)
+ if (old->attr && old->attr != old->attr_buf_static)
{
FcMemFree (FC_MEM_ATTR, 1); /* size is to expensive */
free (old->attr);
}
- FcMemFree (FC_MEM_PSTACK, sizeof (FcPStack));
- free (old);
+
+ if (old == &parse->pstack_static[parse->pstack_static_used - 1])
+ parse->pstack_static_used--;
+ else
+ {
+ FcMemFree (FC_MEM_PSTACK, sizeof (FcPStack));
+ free (old);
+ }
return FcTrue;
}
FcConfigInit (FcConfigParse *parse, const FcChar8 *name, FcConfig *config, XML_Parser parser)
{
parse->pstack = 0;
+ parse->pstack_static_used = 0;
parse->vstack = 0;
+ parse->vstack_static_used = 0;
parse->error = FcFalse;
parse->name = name;
parse->config = config;
}
static const FcChar8 *
-FcConfigGetAttribute (FcConfigParse *parse, char *attr)
+FcConfigGetAttribute (FcConfigParse *parse, const char *attr)
{
FcChar8 **attrs;
if (!parse->pstack)
return 0;
attrs = parse->pstack->attr;
+ if (!attrs)
+ return 0;
+
while (*attrs)
{
if (!strcmp ((char *) *attrs, attr))
if (!parse->pstack)
return;
- s = FcStrBufDone (&parse->pstack->str);
+ s = FcStrBufDoneStatic (&parse->pstack->str);
if (!s)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid integer", s);
else
FcVStackPushInteger (parse, l);
- FcStrFree (s);
+ FcStrBufDestroy (&parse->pstack->str);
}
/*
int slen = strlen (s);
int dlen = strlen (locale_data->decimal_point);
- if (slen + dlen > sizeof (buf))
+ if (slen + dlen > (int) sizeof (buf))
{
if (end)
*end = s;
if (!parse->pstack)
return;
- s = FcStrBufDone (&parse->pstack->str);
+ s = FcStrBufDoneStatic (&parse->pstack->str);
if (!s)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid double", s);
else
FcVStackPushDouble (parse, d);
- FcStrFree (s);
+ FcStrBufDestroy (&parse->pstack->str);
}
static void
enum { m_done, m_xx, m_xy, m_yx, m_yy } matrix_state = m_yy;
FcMatrix m;
- while ((vstack = FcVStackPop (parse)))
+ while ((vstack = FcVStackPeek (parse)))
{
double v;
switch (vstack->tag) {
case m_yy: m.yy = v; break;
default: break;
}
- FcVStackDestroy (vstack);
+ FcVStackPopAndDestroy (parse);
matrix_state--;
}
if (matrix_state != m_done)
}
static FcBool
-FcConfigLexBool (const FcChar8 *bool)
+FcConfigLexBool (FcConfigParse *parse, const FcChar8 *bool_)
{
- if (*bool == 't' || *bool == 'T')
- return FcTrue;
- if (*bool == 'y' || *bool == 'Y')
- return FcTrue;
- if (*bool == '1')
- return FcTrue;
- return FcFalse;
+ FcBool result = FcFalse;
+
+ if (!FcNameBool (bool_, &result))
+ FcConfigMessage (parse, FcSevereWarning, "\"%s\" is not known boolean",
+ bool_);
+ return result;
}
static void
if (!parse->pstack)
return;
- s = FcStrBufDone (&parse->pstack->str);
+ s = FcStrBufDoneStatic (&parse->pstack->str);
if (!s)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
- FcVStackPushBool (parse, FcConfigLexBool (s));
- FcStrFree (s);
+ FcVStackPushBool (parse, FcConfigLexBool (parse, s));
+ FcStrBufDestroy (&parse->pstack->str);
+}
+
+static FcBool
+FcConfigLexBinding (FcConfigParse *parse,
+ const FcChar8 *binding_string,
+ FcValueBinding *binding_ret)
+{
+ FcValueBinding binding;
+
+ if (!binding_string)
+ binding = FcValueBindingWeak;
+ else
+ {
+ if (!strcmp ((char *) binding_string, "weak"))
+ binding = FcValueBindingWeak;
+ else if (!strcmp ((char *) binding_string, "strong"))
+ binding = FcValueBindingStrong;
+ else if (!strcmp ((char *) binding_string, "same"))
+ binding = FcValueBindingSame;
+ else
+ {
+ FcConfigMessage (parse, FcSevereWarning, "invalid binding \"%s\"", binding_string);
+ return FcFalse;
+ }
+ }
+ *binding_ret = binding;
+ return FcTrue;
}
static void
FcVStack *vstack;
FcExpr *left, *expr = 0, *new;
- while ((vstack = FcVStackPop (parse)))
+ while ((vstack = FcVStackPeek (parse)))
{
if (vstack->tag != FcVStackFamily)
{
FcConfigMessage (parse, FcSevereWarning, "non-family");
- FcVStackDestroy (vstack);
+ FcVStackPopAndDestroy (parse);
continue;
}
left = vstack->u.expr;
vstack->tag = FcVStackNone;
- FcVStackDestroy (vstack);
+ FcVStackPopAndDestroy (parse);
if (expr)
{
- new = FcExprCreateOp (left, FcOpComma, expr);
+ new = FcExprCreateOp (parse->config, left, FcOpComma, expr);
if (!new)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
if (!FcVStackPushExpr (parse, tag, expr))
{
FcConfigMessage (parse, FcSevereError, "out of memory");
- if (expr)
- FcExprDestroy (expr);
+ FcExprDestroy (expr);
}
}
}
if (!parse->pstack)
return;
- s = FcStrBufDone (&parse->pstack->str);
+ s = FcStrBufDoneStatic (&parse->pstack->str);
if (!s)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
- expr = FcExprCreateString (s);
- FcStrFree (s);
+ expr = FcExprCreateString (parse->config, s);
+ FcStrBufDestroy (&parse->pstack->str);
if (expr)
FcVStackPushExpr (parse, FcVStackFamily, expr);
}
FcEdit *edit = 0, *next;
FcVStack *vstack;
FcTest *test;
+ FcValueBinding binding;
- while ((vstack = FcVStackPop (parse)))
+ if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding))
+ return;
+ while ((vstack = FcVStackPeek (parse)))
{
switch (vstack->tag) {
case FcVStackFamily:
if (family)
{
- new = FcExprCreateOp (vstack->u.expr, FcOpComma, family);
+ new = FcExprCreateOp (parse->config, vstack->u.expr, FcOpComma, family);
if (!new)
FcConfigMessage (parse, FcSevereError, "out of memory");
else
FcConfigMessage (parse, FcSevereWarning, "bad alias");
break;
}
- FcVStackDestroy (vstack);
+ FcVStackPopAndDestroy (parse);
}
if (!family)
{
}
if (prefer)
{
- edit = FcEditCreate (FcConfigSaveField ("family"),
+ edit = FcEditCreate (parse,
+ FC_FAMILY_OBJECT,
FcOpPrepend,
prefer,
- FcValueBindingWeak);
+ binding);
if (edit)
edit->next = 0;
else
if (accept)
{
next = edit;
- edit = FcEditCreate (FcConfigSaveField ("family"),
+ edit = FcEditCreate (parse,
+ FC_FAMILY_OBJECT,
FcOpAppend,
accept,
- FcValueBindingWeak);
+ binding);
if (edit)
edit->next = next;
else
if (def)
{
next = edit;
- edit = FcEditCreate (FcConfigSaveField ("family"),
+ edit = FcEditCreate (parse,
+ FC_FAMILY_OBJECT,
FcOpAppendLast,
def,
- FcValueBindingWeak);
+ binding);
if (edit)
edit->next = next;
else
}
if (edit)
{
- test = FcTestCreate (FcMatchPattern,
+ test = FcTestCreate (parse, FcMatchPattern,
FcQualAny,
(FcChar8 *) FC_FAMILY,
FcOpEqual,
static FcExpr *
FcPopExpr (FcConfigParse *parse)
{
- FcVStack *vstack = FcVStackPop (parse);
+ FcVStack *vstack = FcVStackPeek (parse);
FcExpr *expr = 0;
if (!vstack)
return 0;
break;
case FcVStackString:
case FcVStackFamily:
- expr = FcExprCreateString (vstack->u.string);
+ expr = FcExprCreateString (parse->config, vstack->u.string);
break;
case FcVStackField:
- expr = FcExprCreateField ((char *) vstack->u.string);
+ expr = FcExprCreateField (parse->config, (char *) vstack->u.string);
break;
case FcVStackConstant:
- expr = FcExprCreateConst (vstack->u.string);
+ expr = FcExprCreateConst (parse->config, vstack->u.string);
break;
case FcVStackGlob:
/* XXX: What's the correct action here? (CDW) */
vstack->tag = FcVStackNone;
break;
case FcVStackInteger:
- expr = FcExprCreateInteger (vstack->u.integer);
+ expr = FcExprCreateInteger (parse->config, vstack->u.integer);
break;
case FcVStackDouble:
- expr = FcExprCreateDouble (vstack->u._double);
+ expr = FcExprCreateDouble (parse->config, vstack->u._double);
break;
case FcVStackMatrix:
- expr = FcExprCreateMatrix (vstack->u.matrix);
+ expr = FcExprCreateMatrix (parse->config, vstack->u.matrix);
break;
case FcVStackBool:
- expr = FcExprCreateBool (vstack->u.bool);
+ expr = FcExprCreateBool (parse->config, vstack->u.bool_);
break;
case FcVStackTest:
break;
default:
break;
}
- FcVStackDestroy (vstack);
+ FcVStackPopAndDestroy (parse);
return expr;
}
{
if (expr)
{
- new = FcExprCreateOp (left, op, expr);
+ new = FcExprCreateOp (parse->config, left, op, expr);
if (!new)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
FcExprDestroy (left);
FcExprDestroy (expr);
- break;
+ return 0;
}
expr = new;
}
if ((operand = FcPopExpr (parse)))
{
- new = FcExprCreateOp (operand, op, 0);
+ new = FcExprCreateOp (parse->config, operand, op, 0);
if (!new)
{
FcExprDestroy (operand);
const FcChar8 *i;
FcBool ignore_missing = FcFalse;
- s = FcStrBufDone (&parse->pstack->str);
+ s = FcStrBufDoneStatic (&parse->pstack->str);
if (!s)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
i = FcConfigGetAttribute (parse, "ignore_missing");
- if (i && FcConfigLexBool ((FcChar8 *) i) == FcTrue)
+ if (i && FcConfigLexBool (parse, (FcChar8 *) i) == FcTrue)
ignore_missing = FcTrue;
if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing))
parse->error = FcTrue;
- FcStrFree (s);
+ FcStrBufDestroy (&parse->pstack->str);
}
typedef struct _FcOpMap {
- char *name;
+ char name[16];
FcOp op;
} FcOpMap;
{ "not_contains", FcOpNotContains }
};
-#define NUM_COMPARE_OPS (sizeof fcCompareOps / sizeof fcCompareOps[0])
+#define NUM_COMPARE_OPS (int) (sizeof fcCompareOps / sizeof fcCompareOps[0])
static FcOp
FcConfigLexCompare (const FcChar8 *compare)
return FcConfigLexOp (compare, fcCompareOps, NUM_COMPARE_OPS);
}
-
static void
FcParseTest (FcConfigParse *parse)
{
kind = FcMatchPattern;
else if (!strcmp ((char *) kind_string, "font"))
kind = FcMatchFont;
+ else if (!strcmp ((char *) kind_string, "scan"))
+ kind = FcMatchScan;
else if (!strcmp ((char *) kind_string, "default"))
kind = FcMatchDefault;
else
FcConfigMessage (parse, FcSevereWarning, "missing test expression");
return;
}
- test = FcTestCreate (kind, qual, name, compare, expr);
+ test = FcTestCreate (parse, kind, qual, name, compare, expr);
if (!test)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
{ "append_last", FcOpAppendLast },
};
-#define NUM_MODE_OPS (sizeof fcModeOps / sizeof fcModeOps[0])
+#define NUM_MODE_OPS (int) (sizeof fcModeOps / sizeof fcModeOps[0])
static FcOp
FcConfigLexMode (const FcChar8 *mode)
{
const FcChar8 *name;
const FcChar8 *mode_string;
- const FcChar8 *binding_string;
FcOp mode;
FcValueBinding binding;
FcExpr *expr;
return;
}
}
- binding_string = FcConfigGetAttribute (parse, "binding");
- if (!binding_string)
- binding = FcValueBindingWeak;
- else
- {
- if (!strcmp ((char *) binding_string, "weak"))
- binding = FcValueBindingWeak;
- else if (!strcmp ((char *) binding_string, "strong"))
- binding = FcValueBindingStrong;
- else if (!strcmp ((char *) binding_string, "same"))
- binding = FcValueBindingSame;
- else
- {
- FcConfigMessage (parse, FcSevereWarning, "invalid edit binding \"%s\"", binding_string);
- return;
- }
- }
+ if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding))
+ return;
+
expr = FcPopBinary (parse, FcOpComma);
- edit = FcEditCreate ((char *) FcStrCopy (name), mode, expr, binding);
+ edit = FcEditCreate (parse, FcObjectFromName ((char *) name),
+ mode, expr, binding);
if (!edit)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
kind = FcMatchPattern;
else if (!strcmp ((char *) kind_name, "font"))
kind = FcMatchFont;
+ else if (!strcmp ((char *) kind_name, "scan"))
+ kind = FcMatchScan;
else
{
FcConfigMessage (parse, FcSevereWarning, "invalid match target \"%s\"", kind_name);
return;
}
}
- while ((vstack = FcVStackPop (parse)))
+ while ((vstack = FcVStackPeek (parse)))
{
switch (vstack->tag) {
case FcVStackTest:
vstack->u.edit->next = edit;
edit = vstack->u.edit;
vstack->tag = FcVStackNone;
+ if (kind == FcMatchScan && edit->object > FC_MAX_BASE_OBJECT)
+ {
+ FcConfigMessage (parse, FcSevereError,
+ "<match target=\"scan\"> cannot edit user-defined object \"%s\"",
+ FcObjectName(edit->object));
+ }
break;
default:
FcConfigMessage (parse, FcSevereWarning, "invalid match element");
break;
}
- FcVStackDestroy (vstack);
+ FcVStackPopAndDestroy (parse);
}
if (!FcConfigAddEdit (parse->config, test, edit, kind))
FcConfigMessage (parse, FcSevereError, "out of memory");
{
FcVStack *vstack;
- while ((vstack = FcVStackPop (parse)))
+ while ((vstack = FcVStackPeek (parse)))
{
switch (vstack->tag) {
case FcVStackGlob:
FcConfigMessage (parse, FcSevereWarning, "bad font selector");
break;
}
- FcVStackDestroy (vstack);
+ FcVStackPopAndDestroy (parse);
}
}
static FcValue
FcPopValue (FcConfigParse *parse)
{
- FcVStack *vstack = FcVStackPop (parse);
+ FcVStack *vstack = FcVStackPeek (parse);
FcValue value;
value.type = FcTypeVoid;
switch (vstack->tag) {
case FcVStackString:
- value.u.s = FcStrCopy (vstack->u.string);
+ value.u.s = FcStrStaticName (vstack->u.string);
if (value.u.s)
value.type = FcTypeString;
break;
value.type = FcTypeMatrix;
break;
case FcVStackBool:
- value.u.b = vstack->u.bool;
+ value.u.b = vstack->u.bool_;
value.type = FcTypeBool;
break;
default:
vstack->tag);
break;
}
- FcVStackDestroy (vstack);
+ FcVStackPopAndDestroy (parse);
return value;
}
return;
}
- name = FcConfigGetAttribute (parse, "name");
+ name = (char *) FcConfigGetAttribute (parse, "name");
if (!name)
{
FcConfigMessage (parse, FcSevereWarning, "missing pattern element name");
- return;
- }
- name = FcObjectStaticName (name);
- if (!name)
- {
- FcConfigMessage (parse, FcSevereError, "out of memory");
+ FcPatternDestroy (pattern);
return;
}
if (!FcPatternAdd (pattern, name, value, FcTrue))
{
FcConfigMessage (parse, FcSevereError, "out of memory");
+ FcValueDestroy(value);
break;
}
+ FcValueDestroy(value);
}
FcVStackPushPattern (parse, pattern);
return;
}
- while ((vstack = FcVStackPop (parse)))
+ while ((vstack = FcVStackPeek (parse)))
{
switch (vstack->tag) {
case FcVStackPattern:
if (!FcPatternAppend (pattern, vstack->u.pattern))
{
FcConfigMessage (parse, FcSevereError, "out of memory");
+ FcPatternDestroy (pattern);
return;
}
break;
FcConfigMessage (parse, FcSevereWarning, "unknown pattern element");
break;
}
- FcVStackDestroy (vstack);
+ FcVStackPopAndDestroy (parse);
}
FcVStackPushPattern (parse, pattern);
{
FcConfigParse *parse = userData;
FcChar8 *data;
-
+#ifdef _WIN32
+ FcChar8 buffer[1000];
+#endif
+
if (!parse->pstack)
return;
switch (parse->pstack->element) {
case FcElementFontconfig:
break;
case FcElementDir:
+ data = FcStrBufDoneStatic (&parse->pstack->str);
+ if (!data)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ break;
+ }
+#ifdef _WIN32
+ if (strcmp (data, "CUSTOMFONTDIR") == 0)
+ {
+ char *p;
+ data = buffer;
+ if (!GetModuleFileName (NULL, buffer, sizeof (buffer) - 20))
+ {
+ FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
+ break;
+ }
+ /*
+ * Must use the multi-byte aware function to search
+ * for backslash because East Asian double-byte code
+ * pages have characters with backslash as the second
+ * byte.
+ */
+ p = _mbsrchr (data, '\\');
+ if (p) *p = '\0';
+ strcat (data, "\\fonts");
+ }
+ else if (strcmp (data, "APPSHAREFONTDIR") == 0)
+ {
+ char *p;
+ data = buffer;
+ if (!GetModuleFileName (NULL, buffer, sizeof (buffer) - 20))
+ {
+ FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
+ break;
+ }
+ p = _mbsrchr (data, '\\');
+ if (p) *p = '\0';
+ strcat (data, "\\..\\share\\fonts");
+ }
+ else if (strcmp (data, "WINDOWSFONTDIR") == 0)
+ {
+ int rc;
+ data = buffer;
+#if _WIN32_WINNT >= 0x0500
+ rc = GetSystemWindowsDirectory (buffer, sizeof (buffer) - 20);
+#else
+ rc = GetWindowsDirectory (buffer, sizeof (buffer) - 20);
+#endif
+ if (rc == 0 || rc > sizeof (buffer) - 20)
+ {
+ FcConfigMessage (parse, FcSevereError, "GetSystemWindowsDirectory failed");
+ break;
+ }
+ if (data [strlen (data) - 1] != '\\')
+ strcat (data, "\\");
+ strcat (data, "fonts");
+ }
+#endif
+ if (strlen ((char *) data) == 0)
+ FcConfigMessage (parse, FcSevereWarning, "empty font directory name ignored");
+ else if (!FcStrUsesHome (data) || FcConfigHome ())
+ {
+ if (!FcConfigAddDir (parse->config, data))
+ FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", data);
+ }
+ FcStrBufDestroy (&parse->pstack->str);
+ break;
+ case FcElementCacheDir:
data = FcStrBufDone (&parse->pstack->str);
if (!data)
{
break;
}
#ifdef _WIN32
- if (strcmp (data, "WINDOWSFONTDIR") == 0)
+ if (strcmp (data, "WINDOWSTEMPDIR_FONTCONFIG_CACHE") == 0)
{
int rc;
FcStrFree (data);
break;
}
FcMemAlloc (FC_MEM_STRING, 1000);
- rc = GetWindowsDirectory (data, 800);
+ rc = GetTempPath (800, data);
if (rc == 0 || rc > 800)
{
- FcConfigMessage (parse, FcSevereError, "GetWindowsDirectory failed");
+ FcConfigMessage (parse, FcSevereError, "GetTempPath failed");
FcStrFree (data);
break;
}
if (data [strlen (data) - 1] != '\\')
strcat (data, "\\");
- strcat (data, "fonts");
+ strcat (data, "fontconfig\\cache");
}
#endif
if (!FcStrUsesHome (data) || FcConfigHome ())
{
- if (!FcConfigAddDir (parse->config, data))
- FcConfigMessage (parse, FcSevereError, "out of memory");
+ if (!FcConfigAddCacheDir (parse->config, data))
+ FcConfigMessage (parse, FcSevereError, "out of memory; cannot add cache directory %s", data);
}
FcStrFree (data);
break;
+
case FcElementCache:
- data = FcStrBufDone (&parse->pstack->str);
+ data = FcStrBufDoneStatic (&parse->pstack->str);
if (!data)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
break;
}
- if (!FcStrUsesHome (data) || FcConfigHome ())
- {
- if (!FcConfigSetCache (parse->config, data))
- FcConfigMessage (parse, FcSevereError, "out of memory");
- }
- FcStrFree (data);
+ /* discard this data; no longer used */
+ FcStrBufDestroy (&parse->pstack->str);
break;
case FcElementInclude:
FcParseInclude (parse);
FcConfigMessage (parse, FcSevereError, "invalid doctype \"%s\"", doctypeName);
}
+#ifdef ENABLE_LIBXML2
+
+static void
+FcInternalSubsetDecl (void *userData,
+ const XML_Char *doctypeName,
+ const XML_Char *sysid,
+ const XML_Char *pubid)
+{
+ FcStartDoctypeDecl (userData, doctypeName, sysid, pubid, 1);
+}
+
+static void
+FcExternalSubsetDecl (void *userData,
+ const XML_Char *doctypeName,
+ const XML_Char *sysid,
+ const XML_Char *pubid)
+{
+ FcStartDoctypeDecl (userData, doctypeName, sysid, pubid, 0);
+}
+
+#else /* ENABLE_LIBXML2 */
+
static void
FcEndDoctypeDecl (void *userData)
{
}
+#endif /* ENABLE_LIBXML2 */
+
+static int
+FcSortCmpStr (const void *a, const void *b)
+{
+ const FcChar8 *as = *((FcChar8 **) a);
+ const FcChar8 *bs = *((FcChar8 **) b);
+ return FcStrCmp (as, bs);
+}
+
static FcBool
FcConfigParseAndLoadDir (FcConfig *config,
const FcChar8 *name,
while (ret && (e = readdir (d)))
{
+ int d_len;
+#define TAIL ".conf"
+#define TAIL_LEN 5
/*
- * Add all files of the form [0-9]*
+ * Add all files of the form [0-9]*.conf
*/
if ('0' <= e->d_name[0] && e->d_name[0] <= '9' &&
- strlen (e->d_name) < FC_MAX_FILE_LEN)
+ (d_len = strlen (e->d_name)) < FC_MAX_FILE_LEN &&
+ d_len > TAIL_LEN &&
+ strcmp (e->d_name + d_len - TAIL_LEN, TAIL) == 0)
{
strcpy ((char *) base, (char *) e->d_name);
if (!FcStrSetAdd (files, file))
{
int i;
qsort (files->strs, files->num, sizeof (FcChar8 *),
- (int (*)(const void *, const void *)) FcStrCmp);
+ (int (*)(const void *, const void *)) FcSortCmpStr);
for (i = 0; ret && i < files->num; i++)
ret = FcConfigParseAndLoad (config, files->strs[i], complain);
}
XML_Parser p;
FcChar8 *filename;
- FILE *f;
+ int fd;
int len;
- void *buf;
FcConfigParse parse;
FcBool error = FcTrue;
+#ifdef ENABLE_LIBXML2
+ xmlSAXHandler sax;
+ char buf[BUFSIZ];
+#else
+ void *buf;
+#endif
+
filename = FcConfigFilename (name);
if (!filename)
goto bail0;
+ if (FcStrSetMember (config->configFiles, filename))
+ {
+ FcStrFree (filename);
+ return FcTrue;
+ }
+
if (!FcStrSetAdd (config->configFiles, filename))
{
FcStrFree (filename);
if (FcDebug () & FC_DBG_CONFIG)
printf ("\tLoading config file %s\n", filename);
- f = fopen ((char *) filename, "r");
- FcStrFree (filename);
- if (!f)
+ fd = open ((char *) filename, O_RDONLY);
+ if (fd == -1) {
+ FcStrFree (filename);
goto bail0;
+ }
+#ifdef ENABLE_LIBXML2
+ memset(&sax, 0, sizeof(sax));
+
+ sax.internalSubset = FcInternalSubsetDecl;
+ sax.externalSubset = FcExternalSubsetDecl;
+ sax.startElement = FcStartElement;
+ sax.endElement = FcEndElement;
+ sax.characters = FcCharacterData;
+
+ p = xmlCreatePushParserCtxt (&sax, &parse, NULL, 0, (const char *) filename);
+#else
p = XML_ParserCreate ("UTF-8");
+#endif
+ FcStrFree (filename);
+
if (!p)
goto bail1;
if (!FcConfigInit (&parse, name, config, p))
goto bail2;
+#ifndef ENABLE_LIBXML2
+
XML_SetUserData (p, &parse);
XML_SetDoctypeDeclHandler (p, FcStartDoctypeDecl, FcEndDoctypeDecl);
XML_SetElementHandler (p, FcStartElement, FcEndElement);
XML_SetCharacterDataHandler (p, FcCharacterData);
+#endif /* ENABLE_LIBXML2 */
+
do {
+#ifndef ENABLE_LIBXML2
buf = XML_GetBuffer (p, BUFSIZ);
if (!buf)
{
FcConfigMessage (&parse, FcSevereError, "cannot get parse buffer");
goto bail3;
}
- len = fread (buf, 1, BUFSIZ, f);
+#endif
+ len = read (fd, buf, BUFSIZ);
if (len < 0)
{
FcConfigMessage (&parse, FcSevereError, "failed reading config file");
goto bail3;
}
+
+#ifdef ENABLE_LIBXML2
+ if (xmlParseChunk (p, buf, len, len == 0))
+#else
if (!XML_ParseBuffer (p, len, len == 0))
+#endif
{
FcConfigMessage (&parse, FcSevereError, "%s",
XML_ErrorString (XML_GetErrorCode (p)));
bail2:
XML_ParserFree (p);
bail1:
- fclose (f);
+ close (fd);
+ fd = -1;
bail0:
if (error && complain)
{
}
return FcTrue;
}
+#define __fcxml__
+#include "fcaliastail.h"
+#undef __fcxml__