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> 2005-01-15 Alan Coopersmith <alan.coopersmith@sun.com>
reviewed by: Keith Packard <keithp@keithp.com> reviewed by: Keith Packard <keithp@keithp.com>

View File

@ -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

View File

@ -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;

View File

@ -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");