Polite typechecking for test and edit expressions. Helps catch errors in
the font configuration.
This commit is contained in:
parent
59e149e757
commit
ca60d2b5c5
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
||||||
|
2005-01-28 Keith Packard <keithp@keithp.com>
|
||||||
|
|
||||||
|
* src/fcint.h:
|
||||||
|
* src/fcname.c: (FcNameBool):
|
||||||
|
* src/fcxml.c: (FcTypeName), (FcTypecheckValue), (FcTypecheckExpr),
|
||||||
|
(FcTestCreate), (FcEditCreate), (FcConfigLexBool), (FcParseBool),
|
||||||
|
(FcParseAlias), (FcParseInclude), (FcParseTest), (FcParseEdit):
|
||||||
|
Polite typechecking for test and edit expressions. Helps
|
||||||
|
catch errors in the font configuration.
|
||||||
|
|
||||||
2005-01-15 Alan Coopersmith <alan.coopersmith@sun.com>
|
2005-01-15 Alan Coopersmith <alan.coopersmith@sun.com>
|
||||||
|
|
||||||
reviewed by: Keith Packard <keithp@keithp.com>
|
reviewed by: Keith Packard <keithp@keithp.com>
|
||||||
|
|
12
src/fcint.h
12
src/fcint.h
|
@ -609,13 +609,6 @@ FcConfigerror (char *fmt, ...);
|
||||||
char *
|
char *
|
||||||
FcConfigSaveField (const char *field);
|
FcConfigSaveField (const char *field);
|
||||||
|
|
||||||
FcTest *
|
|
||||||
FcTestCreate (FcMatchKind kind,
|
|
||||||
FcQual qual,
|
|
||||||
const FcChar8 *field,
|
|
||||||
FcOp compare,
|
|
||||||
FcExpr *expr);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FcTestDestroy (FcTest *test);
|
FcTestDestroy (FcTest *test);
|
||||||
|
|
||||||
|
@ -649,9 +642,6 @@ FcExprCreateOp (FcExpr *left, FcOp op, FcExpr *right);
|
||||||
void
|
void
|
||||||
FcExprDestroy (FcExpr *e);
|
FcExprDestroy (FcExpr *e);
|
||||||
|
|
||||||
FcEdit *
|
|
||||||
FcEditCreate (const char *field, FcOp op, FcExpr *expr, FcValueBinding binding);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FcEditDestroy (FcEdit *e);
|
FcEditDestroy (FcEdit *e);
|
||||||
|
|
||||||
|
@ -697,7 +687,7 @@ FcListPatternMatchAny (const FcPattern *p,
|
||||||
/* fcname.c */
|
/* fcname.c */
|
||||||
|
|
||||||
FcBool
|
FcBool
|
||||||
FcNameBool (FcChar8 *v, FcBool *result);
|
FcNameBool (const FcChar8 *v, FcBool *result);
|
||||||
|
|
||||||
/* fcpat.c */
|
/* fcpat.c */
|
||||||
void
|
void
|
||||||
|
|
|
@ -274,7 +274,7 @@ FcNameConstant (FcChar8 *string, int *result)
|
||||||
}
|
}
|
||||||
|
|
||||||
FcBool
|
FcBool
|
||||||
FcNameBool (FcChar8 *v, FcBool *result)
|
FcNameBool (const FcChar8 *v, FcBool *result)
|
||||||
{
|
{
|
||||||
char c0, c1;
|
char c0, c1;
|
||||||
|
|
||||||
|
|
252
src/fcxml.c
252
src/fcxml.c
|
@ -42,27 +42,6 @@
|
||||||
#undef STRICT
|
#undef STRICT
|
||||||
#endif
|
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FcTestDestroy (FcTest *test)
|
FcTestDestroy (FcTest *test)
|
||||||
|
@ -269,22 +248,6 @@ FcExprDestroy (FcExpr *e)
|
||||||
free (e);
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FcEditDestroy (FcEdit *e)
|
FcEditDestroy (FcEdit *e)
|
||||||
{
|
{
|
||||||
|
@ -528,6 +491,187 @@ FcConfigMessage (FcConfigParse *parse, FcConfigSeverity severe, char *fmt, ...)
|
||||||
va_end (args);
|
va_end (args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static 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
|
||||||
|
FcTypecheckValue (FcConfigParse *parse, FcType value, FcType type)
|
||||||
|
{
|
||||||
|
if (value == FcTypeInteger)
|
||||||
|
value = FcTypeDouble;
|
||||||
|
if (type == FcTypeInteger)
|
||||||
|
type = FcTypeDouble;
|
||||||
|
if (value != type)
|
||||||
|
{
|
||||||
|
if ((value == FcTypeLangSet && type == FcTypeString) ||
|
||||||
|
(value == FcTypeString && type == FcTypeLangSet))
|
||||||
|
return;
|
||||||
|
FcConfigMessage (parse, FcSevereWarning, "saw %s, expected %s",
|
||||||
|
FcTypeName (value), FcTypeName (type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type)
|
||||||
|
{
|
||||||
|
const FcObjectType *o;
|
||||||
|
const FcConstant *c;
|
||||||
|
|
||||||
|
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 (expr->u.field);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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 FcTest *
|
||||||
|
FcTestCreate (FcConfigParse *parse,
|
||||||
|
FcMatchKind kind,
|
||||||
|
FcQual qual,
|
||||||
|
const FcChar8 *field,
|
||||||
|
FcOp compare,
|
||||||
|
FcExpr *expr)
|
||||||
|
{
|
||||||
|
FcTest *test = (FcTest *) malloc (sizeof (FcTest));
|
||||||
|
|
||||||
|
if (test)
|
||||||
|
{
|
||||||
|
const FcObjectType *o;
|
||||||
|
|
||||||
|
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;
|
||||||
|
o = FcNameGetObjectType (test->field);
|
||||||
|
if (o)
|
||||||
|
FcTypecheckExpr (parse, expr, o->type);
|
||||||
|
}
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FcEdit *
|
||||||
|
FcEditCreate (FcConfigParse *parse,
|
||||||
|
const char *field,
|
||||||
|
FcOp op,
|
||||||
|
FcExpr *expr,
|
||||||
|
FcValueBinding binding)
|
||||||
|
{
|
||||||
|
FcEdit *e = (FcEdit *) malloc (sizeof (FcEdit));
|
||||||
|
|
||||||
|
if (e)
|
||||||
|
{
|
||||||
|
const FcObjectType *o;
|
||||||
|
|
||||||
|
e->next = 0;
|
||||||
|
e->field = field; /* already saved in grammar */
|
||||||
|
e->op = op;
|
||||||
|
e->expr = expr;
|
||||||
|
e->binding = binding;
|
||||||
|
o = FcNameGetObjectType (e->field);
|
||||||
|
if (o)
|
||||||
|
FcTypecheckExpr (parse, expr, o->type);
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
FcVStackPush (FcConfigParse *parse, FcVStack *vstack)
|
FcVStackPush (FcConfigParse *parse, FcVStack *vstack)
|
||||||
{
|
{
|
||||||
|
@ -1091,15 +1235,14 @@ FcParseMatrix (FcConfigParse *parse)
|
||||||
}
|
}
|
||||||
|
|
||||||
static FcBool
|
static FcBool
|
||||||
FcConfigLexBool (const FcChar8 *bool)
|
FcConfigLexBool (FcConfigParse *parse, const FcChar8 *bool)
|
||||||
{
|
{
|
||||||
if (*bool == 't' || *bool == 'T')
|
FcBool result = FcFalse;
|
||||||
return FcTrue;
|
|
||||||
if (*bool == 'y' || *bool == 'Y')
|
if (!FcNameBool (bool, &result))
|
||||||
return FcTrue;
|
FcConfigMessage (parse, FcSevereWarning, "\"%s\" is not known boolean",
|
||||||
if (*bool == '1')
|
bool);
|
||||||
return FcTrue;
|
return result;
|
||||||
return FcFalse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1115,7 +1258,7 @@ FcParseBool (FcConfigParse *parse)
|
||||||
FcConfigMessage (parse, FcSevereError, "out of memory");
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FcVStackPushBool (parse, FcConfigLexBool (s));
|
FcVStackPushBool (parse, FcConfigLexBool (parse, s));
|
||||||
FcStrFree (s);
|
FcStrFree (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1247,7 +1390,8 @@ FcParseAlias (FcConfigParse *parse)
|
||||||
}
|
}
|
||||||
if (prefer)
|
if (prefer)
|
||||||
{
|
{
|
||||||
edit = FcEditCreate (FcConfigSaveField ("family"),
|
edit = FcEditCreate (parse,
|
||||||
|
FcConfigSaveField ("family"),
|
||||||
FcOpPrepend,
|
FcOpPrepend,
|
||||||
prefer,
|
prefer,
|
||||||
FcValueBindingWeak);
|
FcValueBindingWeak);
|
||||||
|
@ -1259,7 +1403,8 @@ FcParseAlias (FcConfigParse *parse)
|
||||||
if (accept)
|
if (accept)
|
||||||
{
|
{
|
||||||
next = edit;
|
next = edit;
|
||||||
edit = FcEditCreate (FcConfigSaveField ("family"),
|
edit = FcEditCreate (parse,
|
||||||
|
FcConfigSaveField ("family"),
|
||||||
FcOpAppend,
|
FcOpAppend,
|
||||||
accept,
|
accept,
|
||||||
FcValueBindingWeak);
|
FcValueBindingWeak);
|
||||||
|
@ -1271,7 +1416,8 @@ FcParseAlias (FcConfigParse *parse)
|
||||||
if (def)
|
if (def)
|
||||||
{
|
{
|
||||||
next = edit;
|
next = edit;
|
||||||
edit = FcEditCreate (FcConfigSaveField ("family"),
|
edit = FcEditCreate (parse,
|
||||||
|
FcConfigSaveField ("family"),
|
||||||
FcOpAppendLast,
|
FcOpAppendLast,
|
||||||
def,
|
def,
|
||||||
FcValueBindingWeak);
|
FcValueBindingWeak);
|
||||||
|
@ -1282,7 +1428,7 @@ FcParseAlias (FcConfigParse *parse)
|
||||||
}
|
}
|
||||||
if (edit)
|
if (edit)
|
||||||
{
|
{
|
||||||
test = FcTestCreate (FcMatchPattern,
|
test = FcTestCreate (parse, FcMatchPattern,
|
||||||
FcQualAny,
|
FcQualAny,
|
||||||
(FcChar8 *) FC_FAMILY,
|
(FcChar8 *) FC_FAMILY,
|
||||||
FcOpEqual,
|
FcOpEqual,
|
||||||
|
@ -1437,7 +1583,7 @@ FcParseInclude (FcConfigParse *parse)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i = FcConfigGetAttribute (parse, "ignore_missing");
|
i = FcConfigGetAttribute (parse, "ignore_missing");
|
||||||
if (i && FcConfigLexBool ((FcChar8 *) i) == FcTrue)
|
if (i && FcConfigLexBool (parse, (FcChar8 *) i) == FcTrue)
|
||||||
ignore_missing = FcTrue;
|
ignore_missing = FcTrue;
|
||||||
if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing))
|
if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing))
|
||||||
parse->error = FcTrue;
|
parse->error = FcTrue;
|
||||||
|
@ -1553,7 +1699,7 @@ FcParseTest (FcConfigParse *parse)
|
||||||
FcConfigMessage (parse, FcSevereWarning, "missing test expression");
|
FcConfigMessage (parse, FcSevereWarning, "missing test expression");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
test = FcTestCreate (kind, qual, name, compare, expr);
|
test = FcTestCreate (parse, kind, qual, name, compare, expr);
|
||||||
if (!test)
|
if (!test)
|
||||||
{
|
{
|
||||||
FcConfigMessage (parse, FcSevereError, "out of memory");
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
||||||
|
@ -1626,7 +1772,7 @@ FcParseEdit (FcConfigParse *parse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expr = FcPopBinary (parse, FcOpComma);
|
expr = FcPopBinary (parse, FcOpComma);
|
||||||
edit = FcEditCreate ((char *) FcStrCopy (name), mode, expr, binding);
|
edit = FcEditCreate (parse, (char *) FcStrCopy (name), mode, expr, binding);
|
||||||
if (!edit)
|
if (!edit)
|
||||||
{
|
{
|
||||||
FcConfigMessage (parse, FcSevereError, "out of memory");
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
||||||
|
|
Loading…
Reference in New Issue