Rework to apply the intermixed test and edit elements in one-pass

This commit is contained in:
Akira TAGOH 2013-07-04 19:51:03 +09:00
parent 1162515a98
commit d420e1df98
4 changed files with 331 additions and 351 deletions

View File

@ -214,10 +214,8 @@ FcSubstDestroy (FcSubst *s)
while (s) while (s)
{ {
n = s->next; n = s->next;
if (s->test) if (s->rule)
FcTestDestroy (s->test); FcRuleDestroy (s->rule);
if (s->edit)
FcEditDestroy (s->edit);
free (s); free (s);
s = n; s = n;
} }
@ -226,8 +224,6 @@ FcSubstDestroy (FcSubst *s)
FcExpr * FcExpr *
FcConfigAllocExpr (FcConfig *config) FcConfigAllocExpr (FcConfig *config)
{ {
FcExpr *e;
if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end) if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end)
{ {
FcExprPage *new_page; FcExprPage *new_page;
@ -241,10 +237,7 @@ FcConfigAllocExpr (FcConfig *config)
config->expr_pool = new_page; config->expr_pool = new_page;
} }
e = config->expr_pool->next++; return config->expr_pool->next++;
FcRefInit (&e->ref, 1);
return e;
} }
FcConfig * FcConfig *
@ -649,15 +642,13 @@ FcConfigSetRescanInverval (FcConfig *config, int rescanInterval)
return FcConfigSetRescanInterval (config, rescanInterval); return FcConfigSetRescanInterval (config, rescanInterval);
} }
FcBool FcBool
FcConfigAddEdit (FcConfig *config, FcConfigAddRule (FcConfig *config,
FcTest *test, FcRule *rule,
FcEdit *edit,
FcMatchKind kind) FcMatchKind kind)
{ {
FcSubst *subst, **prev; FcSubst *subst, **prev;
FcTest *t; FcRule *r;
int num; int num;
switch (kind) { switch (kind) {
@ -678,16 +669,19 @@ FcConfigAddEdit (FcConfig *config,
return FcFalse; return FcFalse;
for (; *prev; prev = &(*prev)->next); for (; *prev; prev = &(*prev)->next);
*prev = subst; *prev = subst;
subst->next = 0; subst->next = NULL;
subst->test = test; subst->rule = rule;
subst->edit = edit;
num = 0; num = 0;
for (t = test; t; t = t->next) for (r = rule; r; r = r->next)
{ {
if (t->kind == FcMatchDefault) if (r->type == FcRuleTest)
t->kind = kind; {
if (r->u.test &&
r->u.test->kind == FcMatchDefault)
r->u.test->kind = kind;
num++; num++;
} }
}
if (config->maxObjects < num) if (config->maxObjects < num)
config->maxObjects = num; config->maxObjects = num;
if (FcDebug () & FC_DBG_EDIT) if (FcDebug () & FC_DBG_EDIT)
@ -1491,13 +1485,12 @@ FcConfigSubstituteWithPat (FcConfig *config,
{ {
FcValue v; FcValue v;
FcSubst *s; FcSubst *s;
FcSubState *st; FcRule *r;
int i; FcValueList *l, *value = NULL;
FcTest *t;
FcEdit *e;
FcValueList *l;
FcPattern *m; FcPattern *m;
FcStrSet *strs; FcStrSet *strs;
FcPatternElt *elt = NULL;
FcObject object = FC_INVALID_OBJECT;
if (!config) if (!config)
{ {
@ -1542,10 +1535,6 @@ FcConfigSubstituteWithPat (FcConfig *config,
return FcFalse; return FcFalse;
} }
st = (FcSubState *) malloc (config->maxObjects * sizeof (FcSubState));
if (!st && config->maxObjects)
return FcFalse;
if (FcDebug () & FC_DBG_EDIT) if (FcDebug () & FC_DBG_EDIT)
{ {
printf ("FcConfigSubstitute "); printf ("FcConfigSubstitute ");
@ -1553,121 +1542,108 @@ FcConfigSubstituteWithPat (FcConfig *config,
} }
for (; s; s = s->next) for (; s; s = s->next)
{ {
r = s->rule;
for (; r; r = r->next)
{
switch (r->type) {
case FcRuleUnknown:
/* shouldn't be reached */
break;
case FcRuleTest:
/* /*
* Check the tests to see if * Check the tests to see if
* they all match the pattern * they all match the pattern
*/ */
for (t = s->test, i = 0; t; t = t->next, i++)
{
if (FcDebug () & FC_DBG_EDIT) if (FcDebug () & FC_DBG_EDIT)
{ {
printf ("FcConfigSubstitute test "); printf ("FcConfigSubstitute test ");
FcTestPrint (t); FcTestPrint (r->u.test);
} }
st[i].elt = 0; if (kind == FcMatchFont && r->u.test->kind == FcMatchPattern)
if (kind == FcMatchFont && t->kind == FcMatchPattern)
m = p_pat; m = p_pat;
else else
m = p; m = p;
if (m) if (m)
st[i].elt = FcPatternObjectFindElt (m, t->object); elt = FcPatternObjectFindElt (m, r->u.test->object);
else else
st[i].elt = 0; elt = NULL;
/* /*
* If there's no such field in the font, * If there's no such field in the font,
* then FcQualAll matches while FcQualAny does not * then FcQualAll matches while FcQualAny does not
*/ */
if (!st[i].elt) if (!elt)
{ {
if (t->qual == FcQualAll) if (r->u.test->qual == FcQualAll)
{ {
st[i].value = 0; value = NULL;
continue; continue;
} }
else else
break; {
if (FcDebug () & FC_DBG_EDIT)
printf ("No match\n");
goto bail;
}
} }
/* /*
* Check to see if there is a match, mark the location * Check to see if there is a match, mark the location
* to apply match-relative edits * to apply match-relative edits
*/ */
st[i].value = FcConfigMatchValueList (m, p_pat, kind, t, st[i].elt->values); value = FcConfigMatchValueList (m, p_pat, kind, r->u.test, elt->values);
if (!st[i].value) if (!value ||
break; (r->u.test->qual == FcQualFirst && value != elt->values) ||
if (t->qual == FcQualFirst && st[i].value != st[i].elt->values) (r->u.test->qual == FcQualNotFirst && value == elt->values))
break;
if (t->qual == FcQualNotFirst && st[i].value == st[i].elt->values)
break;
}
if (t)
{ {
if (FcDebug () & FC_DBG_EDIT) if (FcDebug () & FC_DBG_EDIT)
printf ("No match\n"); printf ("No match\n");
continue; goto bail;
} }
object = r->u.test->object;
break;
case FcRuleEdit:
if (FcDebug () & FC_DBG_EDIT) if (FcDebug () & FC_DBG_EDIT)
{ {
printf ("Substitute "); printf ("Substitute ");
FcSubstPrint (s); FcEditPrint (r->u.edit);
printf ("\n\n");
} }
for (e = s->edit; e; e = e->next)
{
/* /*
* Evaluate the list of expressions * Evaluate the list of expressions
*/ */
l = FcConfigValues (p, p_pat,kind, e->expr, e->binding); l = FcConfigValues (p, p_pat,kind, r->u.edit->expr, r->u.edit->binding);
/* /*
* Locate any test associated with this field, skipping * Locate any test associated with this field, skipping
* tests associated with the pattern when substituting in * tests associated with the pattern when substituting in
* the font * the font
*/ */
for (t = s->test, i = 0; t; t = t->next, i++) if (object != r->u.edit->object)
{ value = NULL;
if ((t->kind == FcMatchFont || kind == FcMatchPattern) &&
t->object == e->object) switch (FC_OP_GET_OP (r->u.edit->op)) {
{
/*
* KLUDGE - the pattern may have been reallocated or
* things may have been inserted or deleted above
* this element by other edits. Go back and find
* the element again
*/
if (e != s->edit && st[i].elt)
st[i].elt = FcPatternObjectFindElt (p, t->object);
if (!st[i].elt)
t = 0;
break;
}
}
switch (FC_OP_GET_OP (e->op)) {
case FcOpAssign: case FcOpAssign:
/* /*
* If there was a test, then replace the matched * If there was a test, then replace the matched
* value with the new list of values * value with the new list of values
*/ */
if (t) if (value)
{ {
FcValueList *thisValue = st[i].value; FcValueList *thisValue = value;
FcValueList *nextValue = thisValue; FcValueList *nextValue = thisValue;
/* /*
* Append the new list of values after the current value * Append the new list of values after the current value
*/ */
FcConfigAdd (&st[i].elt->values, thisValue, FcTrue, l, e->object); FcConfigAdd (&elt->values, thisValue, FcTrue, l, r->u.edit->object);
/* /*
* Delete the marked value * Delete the marked value
*/ */
if (thisValue) if (thisValue)
FcConfigDel (&st[i].elt->values, thisValue); FcConfigDel (&elt->values, thisValue);
/* /*
* Adjust any pointers into the value list to ensure * Adjust a pointer into the value list to ensure
* future edits occur at the same place * future edits occur at the same place
*/ */
for (t = s->test, i = 0; t; t = t->next, i++) value = nextValue;
{
if (st[i].value == thisValue)
st[i].value = nextValue;
}
break; break;
} }
/* fall through ... */ /* fall through ... */
@ -1676,71 +1652,64 @@ FcConfigSubstituteWithPat (FcConfig *config,
* Delete all of the values and insert * Delete all of the values and insert
* the new set * the new set
*/ */
FcConfigPatternDel (p, e->object); FcConfigPatternDel (p, r->u.edit->object);
FcConfigPatternAdd (p, e->object, l, FcTrue); FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
/* /*
* Adjust any pointers into the value list as they no * Adjust a pointer into the value list as they no
* longer point to anything valid * longer point to anything valid
*/ */
if (t) value = NULL;
{
FcPatternElt *thisElt = st[i].elt;
for (t = s->test, i = 0; t; t = t->next, i++)
{
if (st[i].elt == thisElt)
st[i].value = 0;
}
}
break; break;
case FcOpPrepend: case FcOpPrepend:
if (t) if (value)
{ {
FcConfigAdd (&st[i].elt->values, st[i].value, FcFalse, l, e->object); FcConfigAdd (&elt->values, value, FcFalse, l, r->u.edit->object);
break; break;
} }
/* fall through ... */ /* fall through ... */
case FcOpPrependFirst: case FcOpPrependFirst:
FcConfigPatternAdd (p, e->object, l, FcFalse); FcConfigPatternAdd (p, r->u.edit->object, l, FcFalse);
break; break;
case FcOpAppend: case FcOpAppend:
if (t) if (value)
{ {
FcConfigAdd (&st[i].elt->values, st[i].value, FcTrue, l, e->object); FcConfigAdd (&elt->values, value, FcTrue, l, r->u.edit->object);
break; break;
} }
/* fall through ... */ /* fall through ... */
case FcOpAppendLast: case FcOpAppendLast:
FcConfigPatternAdd (p, e->object, l, FcTrue); FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
break; break;
case FcOpDelete: case FcOpDelete:
if (t) if (value)
{ {
FcConfigDel (&st[i].elt->values, st[i].value); FcConfigDel (&elt->values, value);
break; break;
} }
/* fall through ... */ /* fall through ... */
case FcOpDeleteAll: case FcOpDeleteAll:
FcConfigPatternDel (p, e->object); FcConfigPatternDel (p, r->u.edit->object);
break; break;
default: default:
FcValueListDestroy (l); FcValueListDestroy (l);
break; break;
} }
}
/* /*
* Now go through the pattern and eliminate * Now go through the pattern and eliminate
* any properties without data * any properties without data
*/ */
for (e = s->edit; e; e = e->next) FcConfigPatternCanon (p, r->u.edit->object);
FcConfigPatternCanon (p, e->object);
if (FcDebug () & FC_DBG_EDIT) if (FcDebug () & FC_DBG_EDIT)
{ {
printf ("FcConfigSubstitute edit"); printf ("FcConfigSubstitute edit");
FcPatternPrint (p); FcPatternPrint (p);
} }
break;
}
}
bail:;
} }
free (st);
if (FcDebug () & FC_DBG_EDIT) if (FcDebug () & FC_DBG_EDIT)
{ {
printf ("FcConfigSubstitute done"); printf ("FcConfigSubstitute done");

View File

@ -427,21 +427,38 @@ FcEditPrint (const FcEdit *edit)
void void
FcSubstPrint (const FcSubst *subst) FcSubstPrint (const FcSubst *subst)
{ {
FcEdit *e; FcRule *r;
FcTest *t; FcRuleType last_type = FcRuleUnknown;
printf ("match\n"); printf ("match\n");
for (t = subst->test; t; t = t->next) for (r = subst->rule; r; r = r->next)
{ {
printf ("\t"); if (last_type != r->type)
FcTestPrint (t); {
switch (r->type) {
case FcRuleTest:
printf ("[test]\n");
break;
case FcRuleEdit:
printf ("[edit]\n");
break;
default:
break;
}
last_type = r->type;
} }
printf ("edit\n");
for (e = subst->edit; e; e = e->next)
{
printf ("\t"); printf ("\t");
FcEditPrint (e); switch (r->type) {
case FcRuleTest:
FcTestPrint (r->u.test);
break;
case FcRuleEdit:
FcEditPrint (r->u.edit);
printf (";\n"); printf (";\n");
break;
default:
break;
}
} }
printf ("\n"); printf ("\n");
} }

View File

@ -241,7 +241,6 @@ typedef struct _FcExprName {
typedef struct _FcExpr { typedef struct _FcExpr {
FcOp op; FcOp op;
FcRef ref;
union { union {
int ival; int ival;
double dval; double dval;
@ -275,7 +274,6 @@ typedef enum _FcQual {
#define FcMatchDefault ((FcMatchKind) -1) #define FcMatchDefault ((FcMatchKind) -1)
typedef struct _FcTest { typedef struct _FcTest {
struct _FcTest *next;
FcMatchKind kind; FcMatchKind kind;
FcQual qual; FcQual qual;
FcObject object; FcObject object;
@ -284,17 +282,28 @@ typedef struct _FcTest {
} FcTest; } FcTest;
typedef struct _FcEdit { typedef struct _FcEdit {
struct _FcEdit *next;
FcObject object; FcObject object;
FcOp op; FcOp op;
FcExpr *expr; FcExpr *expr;
FcValueBinding binding; FcValueBinding binding;
} FcEdit; } FcEdit;
typedef struct _FcSubst { typedef enum _FcRuleType {
struct _FcSubst *next; FcRuleUnknown, FcRuleTest, FcRuleEdit
} FcRuleType;
typedef struct _FcRule {
struct _FcRule *next;
FcRuleType type;
union {
FcTest *test; FcTest *test;
FcEdit *edit; FcEdit *edit;
} u;
} FcRule;
typedef struct _FcSubst {
struct _FcSubst *next;
FcRule *rule;
} FcSubst; } FcSubst;
typedef struct _FcCharLeaf { typedef struct _FcCharLeaf {
@ -614,10 +623,9 @@ FcPrivate FcBool
FcConfigAddBlank (FcConfig *config, FcConfigAddBlank (FcConfig *config,
FcChar32 blank); FcChar32 blank);
FcPrivate FcBool FcBool
FcConfigAddEdit (FcConfig *config, FcConfigAddRule (FcConfig *config,
FcTest *test, FcRule *rule,
FcEdit *edit,
FcMatchKind kind); FcMatchKind kind);
FcPrivate void FcPrivate void
@ -844,6 +852,9 @@ FcTestDestroy (FcTest *test);
FcPrivate void FcPrivate void
FcEditDestroy (FcEdit *e); FcEditDestroy (FcEdit *e);
void
FcRuleDestroy (FcRule *rule);
/* fclang.c */ /* fclang.c */
FcPrivate FcLangSet * FcPrivate FcLangSet *
FcFreeTypeLangSet (const FcCharSet *charset, FcFreeTypeLangSet (const FcCharSet *charset,

View File

@ -62,12 +62,28 @@ FcExprDestroy (FcExpr *e);
void void
FcTestDestroy (FcTest *test) FcTestDestroy (FcTest *test)
{ {
if (test->next)
FcTestDestroy (test->next);
FcExprDestroy (test->expr); FcExprDestroy (test->expr);
free (test); free (test);
} }
void
FcRuleDestroy (FcRule *rule)
{
if (rule->next)
FcRuleDestroy (rule->next);
switch (rule->type) {
case FcRuleTest:
FcTestDestroy (rule->u.test);
break;
case FcRuleEdit:
FcEditDestroy (rule->u.edit);
break;
default:
break;
}
free (rule);
}
static FcExpr * static FcExpr *
FcExprCreateInteger (FcConfig *config, int i) FcExprCreateInteger (FcConfig *config, int i)
{ {
@ -223,24 +239,11 @@ FcExprCreateOp (FcConfig *config, FcExpr *left, FcOp op, FcExpr *right)
return e; return e;
} }
static FcExpr *
FcExprReference (FcExpr *e)
{
if (e)
{
FcRefInc (&e->ref);
}
return e;
}
static void static void
FcExprDestroy (FcExpr *e) FcExprDestroy (FcExpr *e)
{ {
if (!e) if (!e)
return; return;
if (FcRefDec (&e->ref) != 1)
return;
switch (FC_OP_GET_OP (e->op)) { switch (FC_OP_GET_OP (e->op)) {
case FcOpInteger: case FcOpInteger:
break; break;
@ -313,8 +316,6 @@ FcExprDestroy (FcExpr *e)
void void
FcEditDestroy (FcEdit *e) FcEditDestroy (FcEdit *e)
{ {
if (e->next)
FcEditDestroy (e->next);
if (e->expr) if (e->expr)
FcExprDestroy (e->expr); FcExprDestroy (e->expr);
free (e); free (e);
@ -727,7 +728,6 @@ FcTestCreate (FcConfigParse *parse,
{ {
const FcObjectType *o; const FcObjectType *o;
test->next = 0;
test->kind = kind; test->kind = kind;
test->qual = qual; test->qual = qual;
test->object = FcObjectFromName ((const char *) field); test->object = FcObjectFromName ((const char *) field);
@ -740,21 +740,6 @@ FcTestCreate (FcConfigParse *parse,
return test; return test;
} }
static FcTest *
FcTestDuplicate (FcTest *test)
{
FcTest *retval = (FcTest *) malloc (sizeof (FcTest));
if (retval)
{
memcpy (retval, test, sizeof (FcTest));
retval->next = NULL;
retval->expr = FcExprReference (test->expr);
}
return retval;
}
static FcEdit * static FcEdit *
FcEditCreate (FcConfigParse *parse, FcEditCreate (FcConfigParse *parse,
FcObject object, FcObject object,
@ -768,7 +753,6 @@ FcEditCreate (FcConfigParse *parse,
{ {
const FcObjectType *o; const FcObjectType *o;
e->next = 0;
e->object = object; e->object = object;
e->op = op; e->op = op;
e->expr = expr; e->expr = expr;
@ -780,6 +764,34 @@ FcEditCreate (FcConfigParse *parse,
return e; return e;
} }
static FcRule *
FcRuleCreate (FcRuleType type,
void *p)
{
FcRule *r = (FcRule *) malloc (sizeof (FcRule));
if (!r)
return NULL;
r->next = NULL;
r->type = type;
switch (type)
{
case FcRuleTest:
r->u.test = (FcTest *) p;
break;
case FcRuleEdit:
r->u.edit = (FcEdit *) p;
break;
default:
free (r);
r = NULL;
break;
}
return r;
}
static FcVStack * static FcVStack *
FcVStackCreateAndPush (FcConfigParse *parse) FcVStackCreateAndPush (FcConfigParse *parse)
{ {
@ -1685,9 +1697,9 @@ static void
FcParseAlias (FcConfigParse *parse) FcParseAlias (FcConfigParse *parse)
{ {
FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0; FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0;
FcEdit *edit = 0, *next; FcEdit *edit = 0;
FcVStack *vstack; FcVStack *vstack;
FcTest *test = NULL; FcRule *rule = NULL, *r;
FcValueBinding binding; FcValueBinding binding;
if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding)) if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding))
@ -1732,8 +1744,14 @@ FcParseAlias (FcConfigParse *parse)
vstack->tag = FcVStackNone; vstack->tag = FcVStackNone;
break; break;
case FcVStackTest: case FcVStackTest:
vstack->u.test->next = test; if (rule)
test = vstack->u.test; {
r = FcRuleCreate (FcRuleTest, vstack->u.test);
r->next = rule;
rule = r;
}
else
rule = FcRuleCreate (FcRuleTest, vstack->u.test);
vstack->tag = FcVStackNone; vstack->tag = FcVStackNone;
break; break;
default: default:
@ -1751,8 +1769,35 @@ FcParseAlias (FcConfigParse *parse)
FcExprDestroy (accept); FcExprDestroy (accept);
if (def) if (def)
FcExprDestroy (def); FcExprDestroy (def);
if (rule)
FcRuleDestroy (rule);
return; return;
} }
if (!prefer &&
!accept &&
!def)
{
FcExprDestroy (family);
return;
}
else
{
FcTest *t = FcTestCreate (parse, FcMatchPattern,
FcQualAny,
(FcChar8 *) FC_FAMILY,
FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks),
family);
if (rule)
{
for (r = rule; r->next; r = r->next);
r->next = FcRuleCreate (FcRuleTest, t);
r = r->next;
}
else
{
r = rule = FcRuleCreate (FcRuleTest, t);
}
}
if (prefer) if (prefer)
{ {
edit = FcEditCreate (parse, edit = FcEditCreate (parse,
@ -1760,60 +1805,46 @@ FcParseAlias (FcConfigParse *parse)
FcOpPrepend, FcOpPrepend,
prefer, prefer,
binding); binding);
if (edit) if (!edit)
edit->next = 0;
else
FcExprDestroy (prefer); FcExprDestroy (prefer);
else
{
r->next = FcRuleCreate (FcRuleEdit, edit);
r = r->next;
}
} }
if (accept) if (accept)
{ {
next = edit;
edit = FcEditCreate (parse, edit = FcEditCreate (parse,
FC_FAMILY_OBJECT, FC_FAMILY_OBJECT,
FcOpAppend, FcOpAppend,
accept, accept,
binding); binding);
if (edit) if (!edit)
edit->next = next;
else
FcExprDestroy (accept); FcExprDestroy (accept);
else
{
r->next = FcRuleCreate (FcRuleEdit, edit);
r = r->next;
}
} }
if (def) if (def)
{ {
next = edit;
edit = FcEditCreate (parse, edit = FcEditCreate (parse,
FC_FAMILY_OBJECT, FC_FAMILY_OBJECT,
FcOpAppendLast, FcOpAppendLast,
def, def,
binding); binding);
if (edit) if (!edit)
edit->next = next;
else
FcExprDestroy (def); FcExprDestroy (def);
}
if (edit)
{
FcTest *t = FcTestCreate (parse, FcMatchPattern,
FcQualAny,
(FcChar8 *) FC_FAMILY,
FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks),
family);
if (test)
{
FcTest *p = test;
while (p->next)
p = p->next;
p->next = t;
}
else else
test = t; {
if (test) r->next = FcRuleCreate (FcRuleEdit, edit);
if (!FcConfigAddEdit (parse->config, test, edit, FcMatchPattern)) r = r->next;
FcTestDestroy (test);
} }
else }
FcExprDestroy (family); if (!FcConfigAddRule (parse->config, rule, FcMatchPattern))
FcRuleDestroy (rule);
} }
static FcExpr * static FcExpr *
@ -2414,22 +2445,14 @@ FcParseEdit (FcConfigParse *parse)
FcEditDestroy (edit); FcEditDestroy (edit);
} }
typedef struct FcSubstStack {
FcTest *test;
FcEdit *edit;
} FcSubstStack;
static void static void
FcParseMatch (FcConfigParse *parse) FcParseMatch (FcConfigParse *parse)
{ {
const FcChar8 *kind_name; const FcChar8 *kind_name;
FcMatchKind kind; FcMatchKind kind;
FcTest *test = 0;
FcEdit *edit = 0; FcEdit *edit = 0;
FcVStack *vstack; FcVStack *vstack;
FcBool tested = FcFalse; FcRule *rule = NULL, *r;
FcSubstStack *sstack = NULL;
int len, pos = 0, i;
kind_name = FcConfigGetAttribute (parse, "target"); kind_name = FcConfigGetAttribute (parse, "target");
if (!kind_name) if (!kind_name)
@ -2448,55 +2471,29 @@ FcParseMatch (FcConfigParse *parse)
return; return;
} }
} }
len = FcVStackElements(parse);
if (len > 0)
{
sstack = malloc (sizeof (FcSubstStack) * (len + 1));
if (!sstack)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
}
while ((vstack = FcVStackPeek (parse))) while ((vstack = FcVStackPeek (parse)))
{ {
switch ((int) vstack->tag) { switch ((int) vstack->tag) {
case FcVStackTest: case FcVStackTest:
vstack->u.test->next = test; r = FcRuleCreate (FcRuleTest, vstack->u.test);
test = vstack->u.test; if (rule)
r->next = rule;
rule = r;
vstack->tag = FcVStackNone; vstack->tag = FcVStackNone;
tested = FcTrue;
for (i = 0; i < pos; i++)
{
FcTest *t = FcTestDuplicate(test);
t->next = sstack[i].test;
sstack[i].test = t;
}
break; break;
case FcVStackEdit: case FcVStackEdit:
/* due to the reverse traversal, <edit> node appears faster than if (kind == FcMatchScan && vstack->u.edit->object > FC_MAX_BASE_OBJECT)
* <test> node if any. so we have to deal with it here rather than
* the above in FcVStackTest, and put recipes in reverse order.
*/
if (tested)
{
sstack[pos].test = test;
sstack[pos].edit = edit;
pos++;
test = NULL;
edit = NULL;
tested = FcFalse;
}
vstack->u.edit->next = edit;
edit = vstack->u.edit;
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\"", "<match target=\"scan\"> cannot edit user-defined object \"%s\"",
FcObjectName(edit->object)); FcObjectName(edit->object));
break;
} }
r = FcRuleCreate (FcRuleEdit, vstack->u.edit);
if (rule)
r->next = rule;
rule = r;
vstack->tag = FcVStackNone;
break; break;
default: default:
FcConfigMessage (parse, FcSevereWarning, "invalid match element"); FcConfigMessage (parse, FcSevereWarning, "invalid match element");
@ -2504,22 +2501,8 @@ FcParseMatch (FcConfigParse *parse)
} }
FcVStackPopAndDestroy (parse); FcVStackPopAndDestroy (parse);
} }
if (!FcConfigAddEdit (parse->config, test, edit, kind)) if (!FcConfigAddRule (parse->config, rule, kind))
FcConfigMessage (parse, FcSevereError, "out of memory"); FcConfigMessage (parse, FcSevereError, "out of memory");
if (sstack)
{
int i;
for (i = 0; i < pos; i++)
{
if (!FcConfigAddEdit (parse->config, sstack[pos - i - 1].test, sstack[pos - i - 1].edit, kind))
{
FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
}
free (sstack);
}
} }
static void static void