Polite typechecking for test and edit expressions. Helps catch errors in

the font configuration.
This commit is contained in:
Keith Packard 2005-01-28 23:55:14 +00:00
parent 59e149e757
commit ca60d2b5c5
4 changed files with 211 additions and 65 deletions

View File

@ -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>
reviewed by: Keith Packard <keithp@keithp.com>

View File

@ -609,13 +609,6 @@ FcConfigerror (char *fmt, ...);
char *
FcConfigSaveField (const char *field);
FcTest *
FcTestCreate (FcMatchKind kind,
FcQual qual,
const FcChar8 *field,
FcOp compare,
FcExpr *expr);
void
FcTestDestroy (FcTest *test);
@ -649,9 +642,6 @@ FcExprCreateOp (FcExpr *left, FcOp op, FcExpr *right);
void
FcExprDestroy (FcExpr *e);
FcEdit *
FcEditCreate (const char *field, FcOp op, FcExpr *expr, FcValueBinding binding);
void
FcEditDestroy (FcEdit *e);
@ -697,7 +687,7 @@ FcListPatternMatchAny (const FcPattern *p,
/* fcname.c */
FcBool
FcNameBool (FcChar8 *v, FcBool *result);
FcNameBool (const FcChar8 *v, FcBool *result);
/* fcpat.c */
void

View File

@ -274,7 +274,7 @@ FcNameConstant (FcChar8 *string, int *result)
}
FcBool
FcNameBool (FcChar8 *v, FcBool *result)
FcNameBool (const FcChar8 *v, FcBool *result)
{
char c0, c1;

View File

@ -42,27 +42,6 @@
#undef STRICT
#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
FcTestDestroy (FcTest *test)
@ -269,22 +248,6 @@ FcExprDestroy (FcExpr *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
FcEditDestroy (FcEdit *e)
{
@ -528,6 +491,187 @@ FcConfigMessage (FcConfigParse *parse, FcConfigSeverity severe, char *fmt, ...)
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
FcVStackPush (FcConfigParse *parse, FcVStack *vstack)
{
@ -1091,15 +1235,14 @@ FcParseMatrix (FcConfigParse *parse)
}
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
@ -1115,7 +1258,7 @@ FcParseBool (FcConfigParse *parse)
FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
FcVStackPushBool (parse, FcConfigLexBool (s));
FcVStackPushBool (parse, FcConfigLexBool (parse, s));
FcStrFree (s);
}
@ -1247,7 +1390,8 @@ FcParseAlias (FcConfigParse *parse)
}
if (prefer)
{
edit = FcEditCreate (FcConfigSaveField ("family"),
edit = FcEditCreate (parse,
FcConfigSaveField ("family"),
FcOpPrepend,
prefer,
FcValueBindingWeak);
@ -1259,7 +1403,8 @@ FcParseAlias (FcConfigParse *parse)
if (accept)
{
next = edit;
edit = FcEditCreate (FcConfigSaveField ("family"),
edit = FcEditCreate (parse,
FcConfigSaveField ("family"),
FcOpAppend,
accept,
FcValueBindingWeak);
@ -1271,7 +1416,8 @@ FcParseAlias (FcConfigParse *parse)
if (def)
{
next = edit;
edit = FcEditCreate (FcConfigSaveField ("family"),
edit = FcEditCreate (parse,
FcConfigSaveField ("family"),
FcOpAppendLast,
def,
FcValueBindingWeak);
@ -1282,7 +1428,7 @@ FcParseAlias (FcConfigParse *parse)
}
if (edit)
{
test = FcTestCreate (FcMatchPattern,
test = FcTestCreate (parse, FcMatchPattern,
FcQualAny,
(FcChar8 *) FC_FAMILY,
FcOpEqual,
@ -1437,7 +1583,7 @@ FcParseInclude (FcConfigParse *parse)
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;
@ -1553,7 +1699,7 @@ FcParseTest (FcConfigParse *parse)
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");
@ -1626,7 +1772,7 @@ FcParseEdit (FcConfigParse *parse)
}
}
expr = FcPopBinary (parse, FcOpComma);
edit = FcEditCreate ((char *) FcStrCopy (name), mode, expr, binding);
edit = FcEditCreate (parse, (char *) FcStrCopy (name), mode, expr, binding);
if (!edit)
{
FcConfigMessage (parse, FcSevereError, "out of memory");