aboutsummaryrefslogtreecommitdiff
path: root/fontconfig/src/fcxml.c
diff options
context:
space:
mode:
Diffstat (limited to 'fontconfig/src/fcxml.c')
-rw-r--r--fontconfig/src/fcxml.c371
1 files changed, 306 insertions, 65 deletions
diff --git a/fontconfig/src/fcxml.c b/fontconfig/src/fcxml.c
index 9428468a4..ff30b7bbd 100644
--- a/fontconfig/src/fcxml.c
+++ b/fontconfig/src/fcxml.c
@@ -7,9 +7,9 @@
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
+ * documentation, and that the name of the author(s) not be used in
* advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
+ * specific, written prior permission. The authors make no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
@@ -134,6 +134,30 @@ FcExprCreateBool (FcConfig *config, FcBool b)
}
static FcExpr *
+FcExprCreateCharSet (FcConfig *config, FcCharSet *charset)
+{
+ FcExpr *e = FcConfigAllocExpr (config);
+ if (e)
+ {
+ e->op = FcOpCharSet;
+ e->u.cval = FcCharSetCopy (charset);
+ }
+ return e;
+}
+
+static FcExpr *
+FcExprCreateLangSet (FcConfig *config, FcLangSet *langset)
+{
+ FcExpr *e = FcConfigAllocExpr (config);
+ if (e)
+ {
+ e->op = FcOpLangSet;
+ e->u.lval = FcLangSetCopy (langset);
+ }
+ return e;
+}
+
+static FcExpr *
FcExprCreateField (FcConfig *config, const char *field)
{
FcExpr *e = FcConfigAllocExpr (config);
@@ -185,9 +209,14 @@ FcExprDestroy (FcExpr *e)
case FcOpMatrix:
FcMatrixFree (e->u.mval);
break;
+ case FcOpRange:
+ break;
case FcOpCharSet:
FcCharSetDestroy (e->u.cval);
break;
+ case FcOpLangSet:
+ FcLangSetDestroy (e->u.lval);
+ break;
case FcOpBool:
break;
case FcOpField:
@@ -277,8 +306,10 @@ typedef enum _FcElement {
FcElementDouble,
FcElementString,
FcElementMatrix,
+ FcElementRange,
FcElementBool,
- FcElementCharset,
+ FcElementCharSet,
+ FcElementLangSet,
FcElementName,
FcElementConst,
FcElementOr,
@@ -316,7 +347,7 @@ static const struct {
{ "config", FcElementConfig },
{ "match", FcElementMatch },
{ "alias", FcElementAlias },
-
+
{ "blank", FcElementBlank },
{ "rescan", FcElementRescan },
@@ -338,8 +369,10 @@ static const struct {
{ "double", FcElementDouble },
{ "string", FcElementString },
{ "matrix", FcElementMatrix },
+ { "range", FcElementRange },
{ "bool", FcElementBool },
- { "charset", FcElementCharset },
+ { "charset", FcElementCharSet },
+ { "langset", FcElementLangSet },
{ "name", FcElementName },
{ "const", FcElementConst },
{ "or", FcElementOr },
@@ -383,7 +416,7 @@ typedef struct _FcPStack {
FcStrBuf str;
FcChar8 *attr_buf_static[16];
} FcPStack;
-
+
typedef enum _FcVStackTag {
FcVStackNone,
@@ -393,16 +426,19 @@ typedef enum _FcVStackTag {
FcVStackConstant,
FcVStackGlob,
FcVStackPattern,
-
+
FcVStackPrefer,
FcVStackAccept,
FcVStackDefault,
-
+
FcVStackInteger,
FcVStackDouble,
FcVStackMatrix,
+ FcVStackRange,
FcVStackBool,
-
+ FcVStackCharSet,
+ FcVStackLangSet,
+
FcVStackTest,
FcVStackExpr,
FcVStackEdit
@@ -418,7 +454,10 @@ typedef struct _FcVStack {
int integer;
double _double;
FcMatrix *matrix;
+ FcRange range;
FcBool bool_;
+ FcCharSet *charset;
+ FcLangSet *langset;
FcTest *test;
FcQual qual;
@@ -529,7 +568,7 @@ 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;
@@ -551,6 +590,9 @@ FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type)
case FcOpCharSet:
FcTypecheckValue (parse, FcTypeCharSet, type);
break;
+ case FcOpLangSet:
+ FcTypecheckValue (parse, FcTypeLangSet, type);
+ break;
case FcOpNil:
break;
case FcOpField:
@@ -566,8 +608,8 @@ FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type)
if (o)
FcTypecheckValue (parse, o->type, type);
}
- else
- FcConfigMessage (parse, FcSevereWarning,
+ else
+ FcConfigMessage (parse, FcSevereWarning,
"invalid constant used : %s",
expr->u.constant);
break;
@@ -618,7 +660,7 @@ FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type)
static FcTest *
FcTestCreate (FcConfigParse *parse,
- FcMatchKind kind,
+ FcMatchKind kind,
FcQual qual,
const FcChar8 *field,
FcOp compare,
@@ -742,6 +784,18 @@ FcVStackPushMatrix (FcConfigParse *parse, FcMatrix *matrix)
}
static FcBool
+FcVStackPushRange (FcConfigParse *parse, FcRange *range)
+{
+ FcVStack *vstack = FcVStackCreateAndPush (parse);
+ if (!vstack)
+ return FcFalse;
+ vstack->u.range.begin = range->begin;
+ vstack->u.range.end = range->end;
+ vstack->tag = FcVStackRange;
+ return FcTrue;
+}
+
+static FcBool
FcVStackPushBool (FcConfigParse *parse, FcBool bool_)
{
FcVStack *vstack = FcVStackCreateAndPush (parse);
@@ -753,6 +807,34 @@ FcVStackPushBool (FcConfigParse *parse, FcBool bool_)
}
static FcBool
+FcVStackPushCharSet (FcConfigParse *parse, FcCharSet *charset)
+{
+ FcVStack *vstack;
+ if (!charset)
+ return FcFalse;
+ vstack = FcVStackCreateAndPush (parse);
+ if (!vstack)
+ return FcFalse;
+ vstack->u.charset = charset;
+ vstack->tag = FcVStackCharSet;
+ return FcTrue;
+}
+
+static FcBool
+FcVStackPushLangSet (FcConfigParse *parse, FcLangSet *langset)
+{
+ FcVStack *vstack;
+ if (!langset)
+ return FcFalse;
+ vstack = FcVStackCreateAndPush (parse);
+ if (!vstack)
+ return FcFalse;
+ vstack->u.langset = langset;
+ vstack->tag = FcVStackLangSet;
+ return FcTrue;
+}
+
+static FcBool
FcVStackPushTest (FcConfigParse *parse, FcTest *test)
{
FcVStack *vstack = FcVStackCreateAndPush (parse);
@@ -817,7 +899,7 @@ static void
FcVStackPopAndDestroy (FcConfigParse *parse)
{
FcVStack *vstack = parse->vstack;
-
+
if (!vstack || vstack->pstack != parse->pstack)
return;
@@ -843,8 +925,15 @@ FcVStackPopAndDestroy (FcConfigParse *parse)
case FcVStackMatrix:
FcMatrixFree (vstack->u.matrix);
break;
+ case FcVStackRange:
case FcVStackBool:
break;
+ case FcVStackCharSet:
+ FcCharSetDestroy (vstack->u.charset);
+ break;
+ case FcVStackLangSet:
+ FcLangSetDestroy (vstack->u.langset);
+ break;
case FcVStackTest:
FcTestDestroy (vstack->u.test);
break;
@@ -954,8 +1043,8 @@ static FcBool
FcPStackPop (FcConfigParse *parse)
{
FcPStack *old;
-
- if (!parse->pstack)
+
+ if (!parse->pstack)
{
FcConfigMessage (parse, FcSevereError, "mismatching element");
return FcFalse;
@@ -1026,11 +1115,11 @@ FcStartElement(void *userData, const XML_Char *name, const XML_Char **attr)
{
FcConfigParse *parse = userData;
FcElement element;
-
+
element = FcElementMap (name);
if (element == FcElementUnknown)
FcConfigMessage (parse, FcSevereWarning, "unknown element \"%s\"", name);
-
+
if (!FcPStackPush (parse, element, attr))
{
FcConfigMessage (parse, FcSevereError, "out of memory");
@@ -1042,30 +1131,40 @@ FcStartElement(void *userData, const XML_Char *name, const XML_Char **attr)
static void
FcParseBlank (FcConfigParse *parse)
{
- int n = FcVStackElements (parse);
+ int n = FcVStackElements (parse);
+ FcChar32 i;
while (n-- > 0)
{
FcVStack *v = FcVStackFetch (parse, n);
- if (v->tag != FcVStackInteger)
- FcConfigMessage (parse, FcSevereError, "non-integer blank");
- else
+ if (!parse->config->blanks)
{
+ parse->config->blanks = FcBlanksCreate ();
if (!parse->config->blanks)
- {
- parse->config->blanks = FcBlanksCreate ();
- if (!parse->config->blanks)
- {
- FcConfigMessage (parse, FcSevereError, "out of memory");
- break;
- }
- }
+ goto bail;
+ }
+ switch (v->tag) {
+ case FcVStackInteger:
if (!FcBlanksAdd (parse->config->blanks, v->u.integer))
+ goto bail;
+ break;
+ case FcVStackRange:
+ if (v->u.range.begin <= v->u.range.end)
{
- FcConfigMessage (parse, FcSevereError, "out of memory");
- break;
+ for (i = v->u.range.begin; i <= v->u.range.end; i++)
+ {
+ if (!FcBlanksAdd (parse->config->blanks, i))
+ goto bail;
+ }
}
+ break;
+ default:
+ FcConfigMessage (parse, FcSevereError, "invalid element in blank");
+ break;
}
}
+ return;
+ bail:
+ FcConfigMessage (parse, FcSevereError, "out of memory");
}
static void
@@ -1087,7 +1186,7 @@ FcParseInt (FcConfigParse *parse)
{
FcChar8 *s, *end;
int l;
-
+
if (!parse->pstack)
return;
s = FcStrBufDoneStatic (&parse->pstack->str);
@@ -1106,13 +1205,13 @@ FcParseInt (FcConfigParse *parse)
}
/*
- * idea copied from glib g_ascii_strtod with
- * permission of the author (Alexander Larsson)
+ * idea copied from glib g_ascii_strtod with
+ * permission of the author (Alexander Larsson)
*/
#include <locale.h>
-static double
+static double
FcStrtod (char *s, char **end)
{
struct lconv *locale_data;
@@ -1168,7 +1267,7 @@ FcParseDouble (FcConfigParse *parse)
{
FcChar8 *s, *end;
double d;
-
+
if (!parse->pstack)
return;
s = FcStrBufDoneStatic (&parse->pstack->str);
@@ -1190,7 +1289,7 @@ static void
FcParseString (FcConfigParse *parse, FcVStackTag tag)
{
FcChar8 *s;
-
+
if (!parse->pstack)
return;
s = FcStrBufDone (&parse->pstack->str);
@@ -1209,7 +1308,7 @@ FcParseMatrix (FcConfigParse *parse)
FcVStack *vstack;
enum { m_done, m_xx, m_xy, m_yx, m_yy } matrix_state = m_yy;
FcMatrix m;
-
+
while ((vstack = FcVStackPeek (parse)))
{
double v;
@@ -1241,6 +1340,49 @@ FcParseMatrix (FcConfigParse *parse)
FcVStackPushMatrix (parse, &m);
}
+static void
+FcParseRange (FcConfigParse *parse)
+{
+ FcVStack *vstack;
+ FcRange r;
+ FcChar32 n;
+ int count = 1;
+
+ while ((vstack = FcVStackPeek (parse)))
+ {
+ if (count < 0)
+ {
+ FcConfigMessage (parse, FcSevereError, "too many elements in range");
+ return;
+ }
+ switch (vstack->tag) {
+ case FcVStackInteger:
+ n = vstack->u.integer;
+ break;
+ default:
+ FcConfigMessage (parse, FcSevereError, "invalid element in range");
+ break;
+ }
+ if (count == 1)
+ r.end = n;
+ else
+ r.begin = n;
+ count--;
+ FcVStackPopAndDestroy (parse);
+ }
+ if (count < 0)
+ {
+ if (r.begin > r.end)
+ {
+ FcConfigMessage (parse, FcSevereError, "invalid range");
+ return;
+ }
+ FcVStackPushRange (parse, &r);
+ }
+ else
+ FcConfigMessage (parse, FcSevereError, "invalid range");
+}
+
static FcBool
FcConfigLexBool (FcConfigParse *parse, const FcChar8 *bool_)
{
@@ -1269,13 +1411,88 @@ FcParseBool (FcConfigParse *parse)
FcStrBufDestroy (&parse->pstack->str);
}
+static void
+FcParseCharSet (FcConfigParse *parse)
+{
+ FcVStack *vstack;
+ FcCharSet *charset = FcCharSetCreate ();
+ FcChar32 i;
+ int n = 0;
+
+ while ((vstack = FcVStackPeek (parse)))
+ {
+ switch (vstack->tag) {
+ case FcVStackInteger:
+ if (!FcCharSetAddChar (charset, vstack->u.integer))
+ {
+ FcConfigMessage (parse, FcSevereWarning, "invalid character: 0x%04x", vstack->u.integer);
+ }
+ else
+ n++;
+ break;
+ case FcVStackRange:
+ if (vstack->u.range.begin <= vstack->u.range.end)
+ {
+ for (i = vstack->u.range.begin; i <= vstack->u.range.end; i++)
+ {
+ if (!FcCharSetAddChar (charset, i))
+ {
+ FcConfigMessage (parse, FcSevereWarning, "invalid character: 0x%04x", i);
+ }
+ else
+ n++;
+ }
+ }
+ break;
+ default:
+ FcConfigMessage (parse, FcSevereError, "invalid element in charset");
+ break;
+ }
+ FcVStackPopAndDestroy (parse);
+ }
+ if (n > 0)
+ FcVStackPushCharSet (parse, charset);
+ else
+ FcCharSetDestroy (charset);
+}
+
+static void
+FcParseLangSet (FcConfigParse *parse)
+{
+ FcVStack *vstack;
+ FcLangSet *langset = FcLangSetCreate ();
+ int n = 0;
+
+ while ((vstack = FcVStackPeek (parse)))
+ {
+ switch (vstack->tag) {
+ case FcVStackString:
+ if (!FcLangSetAdd (langset, vstack->u.string))
+ {
+ FcConfigMessage (parse, FcSevereWarning, "invalid langset: %s", vstack->u.string);
+ }
+ else
+ n++;
+ break;
+ default:
+ FcConfigMessage (parse, FcSevereError, "invalid element in langset");
+ break;
+ }
+ FcVStackPopAndDestroy (parse);
+ }
+ if (n > 0)
+ FcVStackPushLangSet (parse, langset);
+ else
+ FcLangSetDestroy (langset);
+}
+
static FcBool
FcConfigLexBinding (FcConfigParse *parse,
const FcChar8 *binding_string,
FcValueBinding *binding_ret)
{
FcValueBinding binding;
-
+
if (!binding_string)
binding = FcValueBindingWeak;
else
@@ -1426,7 +1643,7 @@ FcParseAlias (FcConfigParse *parse)
}
if (prefer)
{
- edit = FcEditCreate (parse,
+ edit = FcEditCreate (parse,
FC_FAMILY_OBJECT,
FcOpPrepend,
prefer,
@@ -1515,9 +1732,17 @@ FcPopExpr (FcConfigParse *parse)
case FcVStackMatrix:
expr = FcExprCreateMatrix (parse->config, vstack->u.matrix);
break;
+ case FcVStackRange:
+ break;
case FcVStackBool:
expr = FcExprCreateBool (parse->config, vstack->u.bool_);
break;
+ case FcVStackCharSet:
+ expr = FcExprCreateCharSet (parse->config, vstack->u.charset);
+ break;
+ case FcVStackLangSet:
+ expr = FcExprCreateLangSet (parse->config, vstack->u.langset);
+ break;
case FcVStackTest:
break;
case FcVStackExpr:
@@ -1611,7 +1836,7 @@ FcParseInclude (FcConfigParse *parse)
FcChar8 *s;
const FcChar8 *i;
FcBool ignore_missing = FcFalse;
-
+
s = FcStrBufDoneStatic (&parse->pstack->str);
if (!s)
{
@@ -1637,7 +1862,7 @@ FcConfigLexOp (const FcChar8 *op, const FcOpMap *map, int nmap)
int i;
for (i = 0; i < nmap; i++)
- if (!strcmp ((char *) op, map[i].name))
+ if (!strcmp ((char *) op, map[i].name))
return map[i].op;
return FcOpInvalid;
}
@@ -1846,7 +2071,7 @@ FcParseMatch (FcConfigParse *parse)
vstack->tag = FcVStackNone;
if (kind == FcMatchScan && edit->object > FC_MAX_BASE_OBJECT)
{
- FcConfigMessage (parse, FcSevereError,
+ FcConfigMessage (parse, FcSevereError,
"<match target=\"scan\"> cannot edit user-defined object \"%s\"",
FcObjectName(edit->object));
}
@@ -1870,7 +2095,7 @@ FcParseAcceptRejectFont (FcConfigParse *parse, FcElement element)
{
switch (vstack->tag) {
case FcVStackGlob:
- if (!FcConfigGlobAdd (parse->config,
+ if (!FcConfigGlobAdd (parse->config,
vstack->u.string,
element == FcElementAcceptfont))
{
@@ -1901,12 +2126,12 @@ FcPopValue (FcConfigParse *parse)
{
FcVStack *vstack = FcVStackPeek (parse);
FcValue value;
-
+
value.type = FcTypeVoid;
-
+
if (!vstack)
return value;
-
+
switch (vstack->tag) {
case FcVStackString:
value.u.s = FcStrStaticName (vstack->u.string);
@@ -1934,13 +2159,23 @@ FcPopValue (FcConfigParse *parse)
value.u.b = vstack->u.bool_;
value.type = FcTypeBool;
break;
+ case FcVStackCharSet:
+ value.u.c = FcCharSetCopy (vstack->u.charset);
+ if (value.u.c)
+ value.type = FcTypeCharSet;
+ break;
+ case FcVStackLangSet:
+ value.u.l = FcLangSetCopy (vstack->u.langset);
+ if (value.u.l)
+ value.type = FcTypeLangSet;
+ break;
default:
- FcConfigMessage (parse, FcSevereWarning, "unknown pattern element %d",
+ FcConfigMessage (parse, FcSevereWarning, "unknown pattern element %d",
vstack->tag);
break;
}
FcVStackPopAndDestroy (parse);
-
+
return value;
}
@@ -1964,7 +2199,7 @@ FcParsePatelt (FcConfigParse *parse)
FcPatternDestroy (pattern);
return;
}
-
+
for (;;)
{
value = FcPopValue (parse);
@@ -2199,11 +2434,17 @@ FcEndElement(void *userData, const XML_Char *name)
case FcElementMatrix:
FcParseMatrix (parse);
break;
+ case FcElementRange:
+ FcParseRange (parse);
+ break;
case FcElementBool:
FcParseBool (parse);
break;
- case FcElementCharset:
-/* FcParseCharset (parse); */
+ case FcElementCharSet:
+ FcParseCharSet (parse);
+ break;
+ case FcElementLangSet:
+ FcParseLangSet (parse);
break;
case FcElementSelectfont:
break;
@@ -2296,7 +2537,7 @@ static void
FcCharacterData (void *userData, const XML_Char *s, int len)
{
FcConfigParse *parse = userData;
-
+
if (!parse->pstack)
return;
if (!FcStrBufData (&parse->pstack->str, (FcChar8 *) s, len))
@@ -2382,18 +2623,18 @@ FcConfigParseAndLoadDir (FcConfig *config,
ret = FcFalse;
goto bail1;
}
-
+
strcpy ((char *) file, (char *) dir);
strcat ((char *) file, "/");
base = file + strlen ((char *) file);
-
+
files = FcStrSetCreate ();
if (!files)
{
ret = FcFalse;
goto bail2;
}
-
+
if (FcDebug () & FC_DBG_CONFIG)
printf ("\tScanning config dir %s\n", dir);
@@ -2421,7 +2662,7 @@ FcConfigParseAndLoadDir (FcConfig *config,
if (ret)
{
int i;
- qsort (files->strs, files->num, sizeof (FcChar8 *),
+ qsort (files->strs, files->num, sizeof (FcChar8 *),
(int (*)(const void *, const void *)) FcSortCmpStr);
for (i = 0; ret && i < files->num; i++)
ret = FcConfigParseAndLoad (config, files->strs[i], complain);
@@ -2448,18 +2689,18 @@ FcConfigParseAndLoad (FcConfig *config,
int len;
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);
@@ -2483,11 +2724,11 @@ FcConfigParseAndLoad (FcConfig *config,
printf ("\tLoading config file %s\n", filename);
fd = open ((char *) filename, O_RDONLY);
- if (fd == -1) {
+ if (fd == -1) {
FcStrFree (filename);
goto bail0;
}
-
+
#ifdef ENABLE_LIBXML2
memset(&sax, 0, sizeof(sax));
@@ -2512,7 +2753,7 @@ FcConfigParseAndLoad (FcConfig *config,
#ifndef ENABLE_LIBXML2
XML_SetUserData (p, &parse);
-
+
XML_SetDoctypeDeclHandler (p, FcStartDoctypeDecl, FcEndDoctypeDecl);
XML_SetElementHandler (p, FcStartElement, FcEndElement);
XML_SetCharacterDataHandler (p, FcCharacterData);
@@ -2541,7 +2782,7 @@ FcConfigParseAndLoad (FcConfig *config,
if (!XML_ParseBuffer (p, len, len == 0))
#endif
{
- FcConfigMessage (&parse, FcSevereError, "%s",
+ FcConfigMessage (&parse, FcSevereError, "%s",
XML_ErrorString (XML_GetErrorCode (p)));
goto bail3;
}