/*
- * $XFree86: xc/lib/fontconfig/src/fcxml.c,v 1.6 2002/02/28 16:51:48 keithp Exp $
+ * $RCSId: xc/lib/fontconfig/src/fcxml.c,v 1.21 2002/08/22 18:53:22 keithp Exp $
*
- * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
+ * Copyright © 2002 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
#include <stdarg.h>
#include "fcint.h"
+
+#ifndef HAVE_XMLPARSE_H
+#define HAVE_XMLPARSE_H 0
+#endif
+
#if HAVE_XMLPARSE_H
#include <xmlparse.h>
#else
#endif
FcTest *
-FcTestCreate (FcQual qual, const FcChar8 *field, FcOp compare, FcExpr *expr)
+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;
FcTestDestroy (test->next);
FcExprDestroy (test->expr);
FcStrFree ((FcChar8 *) test->field);
+ FcMemFree (FC_MEM_TEST, sizeof (FcTest));
free (test);
}
if (e)
{
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpInteger;
e->u.ival = i;
}
if (e)
{
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpDouble;
e->u.dval = d;
}
if (e)
{
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpString;
e->u.sval = FcStrCopy (s);
}
if (e)
{
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpMatrix;
e->u.mval = FcMatrixCopy (m);
}
if (e)
{
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpBool;
e->u.bval = b;
}
if (e)
{
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpNil;
}
return e;
if (e)
{
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpField;
e->u.field = (char *) FcStrCopy ((FcChar8 *) field);
}
if (e)
{
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpConst;
e->u.constant = FcStrCopy (constant);
}
if (e)
{
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = op;
e->u.tree.left = left;
e->u.tree.right = right;
case FcOpOr:
case FcOpAnd:
case FcOpEqual:
- case FcOpContains:
case FcOpNotEqual:
case FcOpLess:
case FcOpLessEqual:
case FcOpMore:
case FcOpMoreEqual:
+ case FcOpContains:
+ case FcOpNotContains:
case FcOpPlus:
case FcOpMinus:
case FcOpTimes:
case FcOpInvalid:
break;
}
+ FcMemFree (FC_MEM_EXPR, sizeof (FcExpr));
free (e);
}
FcEdit *
-FcEditCreate (const char *field, FcOp op, FcExpr *expr)
+FcEditCreate (const char *field, FcOp op, FcExpr *expr, FcValueBinding binding)
{
FcEdit *e = (FcEdit *) malloc (sizeof (FcEdit));
e->field = field; /* already saved in grammar */
e->op = op;
e->expr = expr;
+ e->binding = binding;
}
return e;
}
FcElementLessEq,
FcElementMore,
FcElementMoreEq,
+ FcElementContains,
+ FcElementNotContains,
FcElementPlus,
FcElementMinus,
FcElementTimes,
{ "less_eq", FcElementLessEq },
{ "more", FcElementMore },
{ "more_eq", FcElementMoreEq },
+ { "contains", FcElementContains },
+ { "not_contains",FcElementNotContains },
{ "plus", FcElementPlus },
{ "minus", FcElementMinus },
{ "times", FcElementTimes },
new = malloc (sizeof (FcVStack));
if (!new)
return 0;
+ FcMemAlloc (FC_MEM_VSTACK, sizeof (FcVStack));
new->tag = FcVStackNone;
new->prev = 0;
return new;
FcEditDestroy (vstack->u.edit);
break;
}
+ FcMemFree (FC_MEM_VSTACK, sizeof (FcVStack));
free (vstack);
}
}
new = malloc ((i + 1) * sizeof (FcChar8 *) + slen);
if (!new)
return 0;
+ FcMemAlloc (FC_MEM_ATTR, 1); /* size is too expensive */
s = (FcChar8 *) (new + (i + 1));
for (i = 0; attr[i]; i++)
{
if (!new)
return FcFalse;
+ FcMemAlloc (FC_MEM_PSTACK, sizeof (FcPStack));
new->prev = parse->pstack;
new->element = element;
if (attr)
parse->pstack = old->prev;
FcStrBufDestroy (&old->str);
if (old->attr)
+ {
+ FcMemFree (FC_MEM_ATTR, 1); /* size is to expensive */
free (old->attr);
+ }
+ FcMemFree (FC_MEM_PSTACK, sizeof (FcPStack));
free (old);
return FcTrue;
}
FcStrFree (s);
}
+/*
+ * idea copied from glib g_ascii_strtod with
+ * permission of the author (Alexander Larsson)
+ */
+
+#include <locale.h>
+
+static double
+FcStrtod (char *s, char **end)
+{
+ struct lconv *locale_data;
+ char *dot;
+ double v;
+
+ /*
+ * Have to swap the decimal point to match the current locale
+ * if that locale doesn't use 0x2e
+ */
+ if ((dot = strchr (s, 0x2e)) &&
+ (locale_data = localeconv ()) &&
+ (locale_data->decimal_point[0] != 0x2e ||
+ locale_data->decimal_point[1] != 0))
+ {
+ char buf[128];
+ int slen = strlen (s);
+ int dlen = strlen (locale_data->decimal_point);
+
+ if (slen + dlen > sizeof (buf))
+ {
+ if (end)
+ *end = s;
+ v = 0;
+ }
+ else
+ {
+ char *buf_end;
+ /* mantissa */
+ strncpy (buf, s, dot - s);
+ /* decimal point */
+ strcpy (buf + (dot - s), locale_data->decimal_point);
+ /* rest of number */
+ strcpy (buf + (dot - s) + dlen, dot + 1);
+ buf_end = 0;
+ v = strtod (buf, &buf_end);
+ if (buf_end)
+ buf_end = s + (buf_end - buf);
+ if (end)
+ *end = buf_end;
+ }
+ }
+ else
+ v = strtod (s, end);
+ return v;
+}
+
static void
FcParseDouble (FcConfigParse *parse)
{
return;
}
end = 0;
- d = strtod ((char *) s, (char **)&end);
+ d = FcStrtod ((char *) s, (char **)&end);
if (end != s + strlen ((char *) s))
FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid double", s);
else
case m_yy: m.yy = v; break;
default: break;
}
+ FcVStackDestroy (vstack);
matrix_state--;
}
if (matrix_state != m_done)
{
edit = FcEditCreate (FcConfigSaveField ("family"),
FcOpPrepend,
- prefer);
+ prefer,
+ FcValueBindingWeak);
if (edit)
edit->next = 0;
else
next = edit;
edit = FcEditCreate (FcConfigSaveField ("family"),
FcOpAppend,
- accept);
+ accept,
+ FcValueBindingWeak);
if (edit)
edit->next = next;
else
{
next = edit;
edit = FcEditCreate (FcConfigSaveField ("family"),
- FcOpAppendLast,
- def);
+ FcOpAppendLast,
+ def,
+ FcValueBindingWeak);
if (edit)
edit->next = next;
else
}
if (edit)
{
- test = FcTestCreate (FcQualAny,
- FcStrCopy ((FcChar8 *) "family"),
+ test = FcTestCreate (FcMatchPattern,
+ FcQualAny,
+ (FcChar8 *) FC_FAMILY,
FcOpEqual,
family);
if (test)
break;
case FcVStackExpr:
expr = vstack->u.expr;
+ vstack->tag = FcVStackNone;
break;
case FcVStackEdit:
break;
ignore_missing = FcTrue;
if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing))
parse->error = FcTrue;
- free (s);
+ FcStrFree (s);
}
typedef struct _FcOpMap {
{ "less", FcOpLess },
{ "less_eq", FcOpLessEqual },
{ "more", FcOpMore },
- { "more_eq", FcOpMoreEqual }
+ { "more_eq", FcOpMoreEqual },
+ { "contains", FcOpContains },
+ { "not_contains", FcOpNotContains }
};
#define NUM_COMPARE_OPS (sizeof fcCompareOps / sizeof fcCompareOps[0])
static void
FcParseTest (FcConfigParse *parse)
{
+ const FcChar8 *kind_string;
+ FcMatchKind kind;
const FcChar8 *qual_string;
FcQual qual;
const FcChar8 *name;
FcExpr *expr;
FcTest *test;
+ kind_string = FcConfigGetAttribute (parse, "target");
+ if (!kind_string)
+ kind = FcMatchDefault;
+ else
+ {
+ if (!strcmp ((char *) kind_string, "pattern"))
+ kind = FcMatchPattern;
+ else if (!strcmp ((char *) kind_string, "font"))
+ kind = FcMatchFont;
+ else if (!strcmp ((char *) kind_string, "default"))
+ kind = FcMatchDefault;
+ else
+ {
+ FcConfigMessage (parse, FcSevereWarning, "invalid test target \"%s\"", kind_string);
+ return;
+ }
+ }
qual_string = FcConfigGetAttribute (parse, "qual");
if (!qual_string)
qual = FcQualAny;
qual = FcQualAny;
else if (!strcmp ((char *) qual_string, "all"))
qual = FcQualAll;
+ else if (!strcmp ((char *) qual_string, "first"))
+ qual = FcQualFirst;
+ else if (!strcmp ((char *) qual_string, "not_first"))
+ qual = FcQualNotFirst;
else
{
FcConfigMessage (parse, FcSevereWarning, "invalid test qual \"%s\"", qual_string);
- qual = FcQualAny;
+ return;
}
}
name = FcConfigGetAttribute (parse, "name");
if (!name)
{
FcConfigMessage (parse, FcSevereWarning, "missing test name");
- name = (FcChar8 *) FC_FAMILY;
+ return;
}
compare_string = FcConfigGetAttribute (parse, "compare");
if (!compare_string)
if (compare == FcOpInvalid)
{
FcConfigMessage (parse, FcSevereWarning, "invalid test compare \"%s\"", compare_string);
- compare = FcOpEqual;
+ return;
}
}
expr = FcPopExprs (parse, FcOpComma);
FcConfigMessage (parse, FcSevereWarning, "missing test expression");
return;
}
- test = FcTestCreate (qual, name, compare, expr);
+ test = FcTestCreate (kind, qual, name, compare, expr);
if (!test)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
{
const FcChar8 *name;
const FcChar8 *mode_string;
+ const FcChar8 *binding_string;
FcOp mode;
+ FcValueBinding binding;
FcExpr *expr;
FcEdit *edit;
if (!name)
{
FcConfigMessage (parse, FcSevereWarning, "missing edit name");
- name = (FcChar8 *) FC_FAMILY;
+ return;
}
mode_string = FcConfigGetAttribute (parse, "mode");
if (!mode_string)
- mode = FcOpEqual;
+ mode = FcOpAssign;
else
{
mode = FcConfigLexMode (mode_string);
if (mode == FcOpInvalid)
{
FcConfigMessage (parse, FcSevereWarning, "invalid edit mode \"%s\"", mode_string);
- mode = FcOpAssign;
+ return;
+ }
+ }
+ binding_string = FcConfigGetAttribute (parse, "binding");
+ if (!binding_string)
+ binding = FcValueBindingWeak;
+ else
+ {
+ if (!strcmp ((char *) binding_string, "weak"))
+ binding = FcValueBindingWeak;
+ else if (!strcmp ((char *) binding_string, "strong"))
+ binding = FcValueBindingStrong;
+ else if (!strcmp ((char *) binding_string, "same"))
+ binding = FcValueBindingSame;
+ else
+ {
+ FcConfigMessage (parse, FcSevereWarning, "invalid edit binding \"%s\"", binding_string);
+ return;
}
}
expr = FcPopExprs (parse, FcOpComma);
- edit = FcEditCreate ((char *) FcStrCopy (name), mode, expr);
+ edit = FcEditCreate ((char *) FcStrCopy (name), mode, expr, binding);
if (!edit)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
else
{
FcConfigMessage (parse, FcSevereWarning, "invalid match target \"%s\"", kind_name);
- kind = FcMatchPattern;
+ return;
}
}
while ((vstack = FcVStackPop (parse)))
FcConfigMessage (parse, FcSevereError, "out of memory");
break;
}
- if (!FcConfigAddDir (parse->config, data))
- FcConfigMessage (parse, FcSevereError, "out of memory");
- free (data);
+ if (!FcStrUsesHome (data) || FcConfigHome ())
+ {
+ if (!FcConfigAddDir (parse->config, data))
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ }
+ FcStrFree (data);
break;
case FcElementCache:
data = FcStrBufDone (&parse->pstack->str);
FcConfigMessage (parse, FcSevereError, "out of memory");
break;
}
- if (!FcConfigSetCache (parse->config, data))
- FcConfigMessage (parse, FcSevereError, "out of memory");
- free (data);
+ if (!FcStrUsesHome (data) || FcConfigHome ())
+ {
+ if (!FcConfigSetCache (parse->config, data))
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ }
+ FcStrFree (data);
break;
case FcElementInclude:
FcParseInclude (parse);
case FcElementMoreEq:
FcParseExpr (parse, FcOpMoreEqual);
break;
+ case FcElementContains:
+ FcParseExpr (parse, FcOpContains);
+ break;
+ case FcElementNotContains:
+ FcParseExpr (parse, FcOpNotContains);
+ break;
case FcElementPlus:
FcParseExpr (parse, FcOpPlus);
break;
filename = FcConfigFilename (name);
if (!filename)
goto bail0;
+
+ if (!FcStrSetAdd (config->configFiles, filename))
+ {
+ FcStrFree (filename);
+ goto bail0;
+ }
+
f = fopen ((char *) filename, "r");
- free (filename);
+ FcStrFree (filename);
if (!f)
goto bail0;