X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=src%2Ffcxml.c;h=a25ffe74fee474be05469316e80a3d73070829a5;hb=39861b7d9c69e71b9a8fb0d0d04279520cb30f04;hp=950bc9aa015003d91e8eb6196fa8dc0c28c5fba9;hpb=67accef4d3e245c1dea341e633d82b14aa03432a;p=fontconfig.git diff --git a/src/fcxml.c b/src/fcxml.c index 950bc9a..a25ffe7 100644 --- a/src/fcxml.c +++ b/src/fcxml.c @@ -1,5 +1,5 @@ /* - * $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 * @@ -22,10 +22,24 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include #include "fcint.h" +#include +#include #include +#ifdef ENABLE_LIBXML2 + +#include + +#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 @@ -36,6 +50,8 @@ #include #endif +#endif /* ENABLE_LIBXML2 */ + #ifdef _WIN32 #define STRICT #include @@ -49,7 +65,6 @@ FcTestDestroy (FcTest *test) if (test->next) FcTestDestroy (test->next); FcExprDestroy (test->expr); - FcStrFree ((FcChar8 *) test->field); FcMemFree (FC_MEM_TEST, sizeof (FcTest)); free (test); } @@ -146,7 +161,7 @@ FcExprCreateField (const char *field) { FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr)); e->op = FcOpField; - e->u.field = (char *) FcStrCopy ((FcChar8 *) field); + e->u.object = FcObjectFromName (field); } return e; } @@ -202,7 +217,6 @@ FcExprDestroy (FcExpr *e) case FcOpBool: break; case FcOpField: - FcStrFree ((FcChar8 *) e->u.field); break; case FcOpConst: FcStrFree (e->u.constant); @@ -253,7 +267,6 @@ FcEditDestroy (FcEdit *e) { if (e->next) FcEditDestroy (e->next); - FcStrFree ((FcChar8 *) e->field); if (e->expr) FcExprDestroy (e->expr); free (e); @@ -269,6 +282,7 @@ typedef enum _FcElement { FcElementNone, FcElementFontconfig, FcElementDir, + FcElementCacheDir, FcElementCache, FcElementInclude, FcElementConfig, @@ -323,12 +337,13 @@ typedef enum _FcElement { FcElementUnknown } FcElement; -static struct { +static const struct { const char name[16]; FcElement element; } fcElementMap[] = { { "fontconfig", FcElementFontconfig }, { "dir", FcElementDir }, + { "cachedir", FcElementCacheDir }, { "cache", FcElementCache }, { "include", FcElementInclude }, { "config", FcElementConfig }, @@ -435,7 +450,7 @@ typedef struct _FcVStack { int integer; double _double; FcMatrix *matrix; - FcBool bool; + FcBool bool_; FcTest *test; FcQual qual; @@ -454,6 +469,10 @@ typedef struct _FcConfigParse { 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 { @@ -477,10 +496,10 @@ FcConfigMessage (FcConfigParse *parse, FcConfigSeverity severe, const char *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; } @@ -530,6 +549,8 @@ FcTypecheckValue (FcConfigParse *parse, FcType value, FcType 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)); } @@ -541,6 +562,10 @@ FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type) const FcObjectType *o; const FcConstant *c; + /* If parsing the expression failed, some nodes may be NULL */ + if (!expr) + return; + switch (expr->op) { case FcOpInteger: case FcOpDouble: @@ -561,7 +586,7 @@ FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type) case FcOpNil: break; case FcOpField: - o = FcNameGetObjectType (expr->u.field); + o = FcNameGetObjectType (FcObjectName (expr->u.object)); if (o) FcTypecheckValue (parse, o->type, type); break; @@ -573,6 +598,10 @@ FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type) 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); @@ -637,10 +666,10 @@ FcTestCreate (FcConfigParse *parse, test->next = 0; test->kind = kind; test->qual = qual; - test->field = (char *) FcStrCopy (field); + test->object = FcObjectFromName ((const char *) field); test->op = compare; test->expr = expr; - o = FcNameGetObjectType (test->field); + o = FcNameGetObjectType (FcObjectName (test->object)); if (o) FcTypecheckExpr (parse, expr, o->type); } @@ -649,7 +678,7 @@ FcTestCreate (FcConfigParse *parse, static FcEdit * FcEditCreate (FcConfigParse *parse, - const char *field, + FcObject object, FcOp op, FcExpr *expr, FcValueBinding binding) @@ -661,197 +690,141 @@ FcEditCreate (FcConfigParse *parse, const FcObjectType *o; e->next = 0; - e->field = field; /* already saved in grammar */ + e->object = object; e->op = op; e->expr = expr; e->binding = binding; - o = FcNameGetObjectType (e->field); + o = FcNameGetObjectType (FcObjectName (e->object)); if (o) FcTypecheckExpr (parse, expr, o->type); } return e; } -static void -FcVStackPush (FcConfigParse *parse, FcVStack *vstack) -{ - vstack->prev = parse->vstack; - vstack->pstack = parse->pstack ? parse->pstack->prev : 0; - parse->vstack = vstack; -} - static FcVStack * -FcVStackCreate (void) +FcVStackCreateAndPush (FcConfigParse *parse) { FcVStack *new; - new = malloc (sizeof (FcVStack)); - if (!new) - return 0; - FcMemAlloc (FC_MEM_VSTACK, sizeof (FcVStack)); + 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; - return new; -} -static void -FcVStackDestroy (FcVStack *vstack) -{ - FcVStack *prev; + new->prev = parse->vstack; + new->pstack = parse->pstack ? parse->pstack->prev : 0; + parse->vstack = new; - for (; vstack; vstack = prev) - { - 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); - } + 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; } @@ -864,28 +837,73 @@ FcVStackFetch (FcConfigParse *parse, int off) 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 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; + } + + 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 @@ -904,7 +922,6 @@ FcVStackElements (FcConfigParse *parse) static FcChar8 ** FcConfigSaveAttr (const XML_Char **attr) { - int n; int slen; int i; FcChar8 **new; @@ -914,11 +931,15 @@ FcConfigSaveAttr (const XML_Char **attr) return 0; slen = 0; for (i = 0; attr[i]; i++) - slen += strlen (attr[i]) + 1; - n = i; + slen += strlen ((char *) attr[i]) + 1; + if (i == 0) + return 0; new = malloc ((i + 1) * sizeof (FcChar8 *) + 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++) @@ -934,21 +955,21 @@ FcConfigSaveAttr (const XML_Char **attr) 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); FcStrBufInit (&new->str, 0, 0); parse->pstack = new; return FcTrue; @@ -973,8 +994,14 @@ FcPStackPop (FcConfigParse *parse) 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; } @@ -982,7 +1009,9 @@ static FcBool 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; @@ -1005,6 +1034,9 @@ FcConfigGetAttribute (FcConfigParse *parse, const char *attr) return 0; attrs = parse->pstack->attr; + if (!attrs) + return 0; + while (*attrs) { if (!strcmp ((char *) *attrs, attr)) @@ -1083,7 +1115,7 @@ FcParseInt (FcConfigParse *parse) if (!parse->pstack) return; - s = FcStrBufDone (&parse->pstack->str); + s = FcStrBufDoneStatic (&parse->pstack->str); if (!s) { FcConfigMessage (parse, FcSevereError, "out of memory"); @@ -1095,7 +1127,7 @@ FcParseInt (FcConfigParse *parse) FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid integer", s); else FcVStackPushInteger (parse, l); - FcStrFree (s); + FcStrBufDestroy (&parse->pstack->str); } /* @@ -1164,7 +1196,7 @@ FcParseDouble (FcConfigParse *parse) if (!parse->pstack) return; - s = FcStrBufDone (&parse->pstack->str); + s = FcStrBufDoneStatic (&parse->pstack->str); if (!s) { FcConfigMessage (parse, FcSevereError, "out of memory"); @@ -1176,7 +1208,7 @@ FcParseDouble (FcConfigParse *parse) FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid double", s); else FcVStackPushDouble (parse, d); - FcStrFree (s); + FcStrBufDestroy (&parse->pstack->str); } static void @@ -1203,7 +1235,7 @@ FcParseMatrix (FcConfigParse *parse) 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) { @@ -1225,7 +1257,7 @@ FcParseMatrix (FcConfigParse *parse) case m_yy: m.yy = v; break; default: break; } - FcVStackDestroy (vstack); + FcVStackPopAndDestroy (parse); matrix_state--; } if (matrix_state != m_done) @@ -1235,13 +1267,13 @@ FcParseMatrix (FcConfigParse *parse) } static FcBool -FcConfigLexBool (FcConfigParse *parse, const FcChar8 *bool) +FcConfigLexBool (FcConfigParse *parse, const FcChar8 *bool_) { FcBool result = FcFalse; - if (!FcNameBool (bool, &result)) + if (!FcNameBool (bool_, &result)) FcConfigMessage (parse, FcSevereWarning, "\"%s\" is not known boolean", - bool); + bool_); return result; } @@ -1252,14 +1284,41 @@ FcParseBool (FcConfigParse *parse) 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 (parse, s)); - FcStrFree (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 @@ -1268,17 +1327,17 @@ FcParseFamilies (FcConfigParse *parse, FcVStackTag tag) 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); @@ -1299,8 +1358,7 @@ FcParseFamilies (FcConfigParse *parse, FcVStackTag tag) if (!FcVStackPushExpr (parse, tag, expr)) { FcConfigMessage (parse, FcSevereError, "out of memory"); - if (expr) - FcExprDestroy (expr); + FcExprDestroy (expr); } } } @@ -1313,14 +1371,14 @@ FcParseFamily (FcConfigParse *parse) 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); + FcStrBufDestroy (&parse->pstack->str); if (expr) FcVStackPushExpr (parse, FcVStackFamily, expr); } @@ -1332,8 +1390,11 @@ FcParseAlias (FcConfigParse *parse) 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: @@ -1375,7 +1436,7 @@ FcParseAlias (FcConfigParse *parse) FcConfigMessage (parse, FcSevereWarning, "bad alias"); break; } - FcVStackDestroy (vstack); + FcVStackPopAndDestroy (parse); } if (!family) { @@ -1391,10 +1452,10 @@ FcParseAlias (FcConfigParse *parse) if (prefer) { edit = FcEditCreate (parse, - FcConfigSaveField ("family"), + FC_FAMILY_OBJECT, FcOpPrepend, prefer, - FcValueBindingWeak); + binding); if (edit) edit->next = 0; else @@ -1404,10 +1465,10 @@ FcParseAlias (FcConfigParse *parse) { next = edit; edit = FcEditCreate (parse, - FcConfigSaveField ("family"), + FC_FAMILY_OBJECT, FcOpAppend, accept, - FcValueBindingWeak); + binding); if (edit) edit->next = next; else @@ -1417,10 +1478,10 @@ FcParseAlias (FcConfigParse *parse) { next = edit; edit = FcEditCreate (parse, - FcConfigSaveField ("family"), + FC_FAMILY_OBJECT, FcOpAppendLast, def, - FcValueBindingWeak); + binding); if (edit) edit->next = next; else @@ -1444,7 +1505,7 @@ FcParseAlias (FcConfigParse *parse) static FcExpr * FcPopExpr (FcConfigParse *parse) { - FcVStack *vstack = FcVStackPop (parse); + FcVStack *vstack = FcVStackPeek (parse); FcExpr *expr = 0; if (!vstack) return 0; @@ -1480,7 +1541,7 @@ FcPopExpr (FcConfigParse *parse) expr = FcExprCreateMatrix (vstack->u.matrix); break; case FcVStackBool: - expr = FcExprCreateBool (vstack->u.bool); + expr = FcExprCreateBool (vstack->u.bool_); break; case FcVStackTest: break; @@ -1493,7 +1554,7 @@ FcPopExpr (FcConfigParse *parse) default: break; } - FcVStackDestroy (vstack); + FcVStackPopAndDestroy (parse); return expr; } @@ -1521,7 +1582,7 @@ FcPopBinary (FcConfigParse *parse, FcOp op) FcConfigMessage (parse, FcSevereError, "out of memory"); FcExprDestroy (left); FcExprDestroy (expr); - break; + return 0; } expr = new; } @@ -1576,7 +1637,7 @@ FcParseInclude (FcConfigParse *parse) 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"); @@ -1587,7 +1648,7 @@ FcParseInclude (FcConfigParse *parse) ignore_missing = FcTrue; if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing)) parse->error = FcTrue; - FcStrFree (s); + FcStrBufDestroy (&parse->pstack->str); } typedef struct _FcOpMap { @@ -1625,7 +1686,6 @@ FcConfigLexCompare (const FcChar8 *compare) return FcConfigLexOp (compare, fcCompareOps, NUM_COMPARE_OPS); } - static void FcParseTest (FcConfigParse *parse) { @@ -1648,6 +1708,8 @@ 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 @@ -1730,7 +1792,6 @@ FcParseEdit (FcConfigParse *parse) { const FcChar8 *name; const FcChar8 *mode_string; - const FcChar8 *binding_string; FcOp mode; FcValueBinding binding; FcExpr *expr; @@ -1754,25 +1815,12 @@ FcParseEdit (FcConfigParse *parse) 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 (parse, (char *) FcStrCopy (name), mode, expr, binding); + edit = FcEditCreate (parse, FcObjectFromName ((char *) name), + mode, expr, binding); if (!edit) { FcConfigMessage (parse, FcSevereError, "out of memory"); @@ -1801,13 +1849,15 @@ FcParseMatch (FcConfigParse *parse) 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: @@ -1819,12 +1869,18 @@ FcParseMatch (FcConfigParse *parse) vstack->u.edit->next = edit; edit = vstack->u.edit; vstack->tag = FcVStackNone; + if (kind == FcMatchScan && edit->object > FC_MAX_BASE_OBJECT) + { + FcConfigMessage (parse, FcSevereError, + " 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"); @@ -1835,7 +1891,7 @@ FcParseAcceptRejectFont (FcConfigParse *parse, FcElement element) { FcVStack *vstack; - while ((vstack = FcVStackPop (parse))) + while ((vstack = FcVStackPeek (parse))) { switch (vstack->tag) { case FcVStackGlob: @@ -1860,7 +1916,7 @@ FcParseAcceptRejectFont (FcConfigParse *parse, FcElement element) FcConfigMessage (parse, FcSevereWarning, "bad font selector"); break; } - FcVStackDestroy (vstack); + FcVStackPopAndDestroy (parse); } } @@ -1868,7 +1924,7 @@ FcParseAcceptRejectFont (FcConfigParse *parse, FcElement element) static FcValue FcPopValue (FcConfigParse *parse) { - FcVStack *vstack = FcVStackPop (parse); + FcVStack *vstack = FcVStackPeek (parse); FcValue value; value.type = FcTypeVoid; @@ -1900,7 +1956,7 @@ FcPopValue (FcConfigParse *parse) value.type = FcTypeMatrix; break; case FcVStackBool: - value.u.b = vstack->u.bool; + value.u.b = vstack->u.bool_; value.type = FcTypeBool; break; default: @@ -1908,7 +1964,7 @@ FcPopValue (FcConfigParse *parse) vstack->tag); break; } - FcVStackDestroy (vstack); + FcVStackPopAndDestroy (parse); return value; } @@ -1930,6 +1986,7 @@ FcParsePatelt (FcConfigParse *parse) if (!name) { FcConfigMessage (parse, FcSevereWarning, "missing pattern element name"); + FcPatternDestroy (pattern); return; } @@ -1941,8 +1998,10 @@ FcParsePatelt (FcConfigParse *parse) if (!FcPatternAdd (pattern, name, value, FcTrue)) { FcConfigMessage (parse, FcSevereError, "out of memory"); + FcValueDestroy(value); break; } + FcValueDestroy(value); } FcVStackPushPattern (parse, pattern); @@ -1960,13 +2019,14 @@ FcParsePattern (FcConfigParse *parse) 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; @@ -1974,7 +2034,7 @@ FcParsePattern (FcConfigParse *parse) FcConfigMessage (parse, FcSevereWarning, "unknown pattern element"); break; } - FcVStackDestroy (vstack); + FcVStackPopAndDestroy (parse); } FcVStackPushPattern (parse, pattern); @@ -1994,14 +2054,56 @@ FcEndElement(void *userData, const XML_Char *name) case FcElementFontconfig: break; case FcElementDir: - data = FcStrBufDone (&parse->pstack->str); + data = FcStrBufDoneStatic (&parse->pstack->str); if (!data) { FcConfigMessage (parse, FcSevereError, "out of memory"); break; } #ifdef _WIN32 - if (strcmp (data, "WINDOWSFONTDIR") == 0) + if (strcmp (data, "CUSTOMFONTDIR") == 0) + { + char *p; + FcStrFree (data); + data = malloc (1000); + if (!data) + { + FcConfigMessage (parse, FcSevereError, "out of memory"); + break; + } + FcMemAlloc (FC_MEM_STRING, 1000); + if(!GetModuleFileName(NULL, data, 1000)) + { + FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed"); + FcStrFree (data); + break; + } + p = strrchr (data, '\\'); + if (p) *p = '\0'; + strcat (data, "\\fonts"); + } + else if (strcmp (data, "APPSHAREFONTDIR") == 0) + { + char *p; + FcStrFree (data); + data = malloc (1000); + if (!data) + { + FcConfigMessage (parse, FcSevereError, "out of memory"); + break; + } + FcMemAlloc (FC_MEM_STRING, 1000); + if(!GetModuleFileName(NULL, data, 1000)) + { + FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed"); + FcStrFree (data); + break; + } + p = strrchr (data, '\\'); + if (p) *p = '\0'; + strcat (data, "\\..\\share\\fonts"); + } + else if (strcmp (data, "WINDOWSFONTDIR") == 0) { int rc; FcStrFree (data); @@ -2024,27 +2126,64 @@ FcEndElement(void *userData, const XML_Char *name) strcat (data, "fonts"); } #endif - if (!FcStrUsesHome (data) || FcConfigHome ()) + 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"); + FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", data); } - FcStrFree (data); + FcStrBufDestroy (&parse->pstack->str); break; - case FcElementCache: + case FcElementCacheDir: data = FcStrBufDone (&parse->pstack->str); if (!data) { FcConfigMessage (parse, FcSevereError, "out of memory"); break; } - if (!FcStrUsesHome (data) || FcConfigHome ()) +#ifdef _WIN32 + if (strcmp (data, "WINDOWSTEMPDIR_FONTCONFIG_CACHE") == 0) { - if (!FcConfigSetCache (parse->config, data)) + int rc; + FcStrFree (data); + data = malloc (1000); + if (!data) + { FcConfigMessage (parse, FcSevereError, "out of memory"); + break; + } + FcMemAlloc (FC_MEM_STRING, 1000); + rc = GetTempPath (800, data); + if (rc == 0 || rc > 800) + { + FcConfigMessage (parse, FcSevereError, "GetWindowsDirectory failed"); + FcStrFree (data); + break; + } + if (data [strlen (data) - 1] != '\\') + strcat (data, "\\"); + strcat (data, "fontconfig\\cache"); + } +#endif + if (!FcStrUsesHome (data) || FcConfigHome ()) + { + if (!FcConfigAddCacheDir (parse->config, data)) + FcConfigMessage (parse, FcSevereError, "out of memory; cannot add cache directory %s", data); } FcStrFree (data); break; + + case FcElementCache: + data = FcStrBufDoneStatic (&parse->pstack->str); + if (!data) + { + FcConfigMessage (parse, FcSevereError, "out of memory"); + break; + } + /* discard this data; no longer used */ + FcStrBufDestroy (&parse->pstack->str); + break; case FcElementInclude: FcParseInclude (parse); break; @@ -2213,11 +2352,43 @@ FcStartDoctypeDecl (void *userData, 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, @@ -2287,7 +2458,7 @@ FcConfigParseAndLoadDir (FcConfig *config, { 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); } @@ -2309,16 +2480,28 @@ FcConfigParseAndLoad (FcConfig *config, 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); @@ -2335,38 +2518,64 @@ FcConfigParseAndLoad (FcConfig *config, 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))); @@ -2379,8 +2588,8 @@ bail3: bail2: XML_ParserFree (p); bail1: - fclose (f); - f = NULL; + close (fd); + fd = -1; bail0: if (error && complain) { @@ -2392,3 +2601,6 @@ bail0: } return FcTrue; } +#define __fcxml__ +#include "fcaliastail.h" +#undef __fcxml__