/*
- * $XFree86: xc/lib/fontconfig/src/fcxml.c,v 1.5 2002/02/22 18:54:07 keithp Exp $
+ * $XFree86: xc/lib/fontconfig/src/fcxml.c,v 1.16 2002/07/12 19:19:16 keithp Exp $
*
* Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
*
*/
#include <stdarg.h>
-#include <expat.h>
#include "fcint.h"
+#ifndef HAVE_EXPAT
+#define HAVE_EXPAT 1
+#endif
+
+#ifndef HAVE_XML2
+#define HAVE_XML2 0
+#endif
+
+#if HAVE_EXPAT
+#ifndef HAVE_XMLPARSE_H
+#define HAVE_XMLPARSE_H 0
+#endif
+#if HAVE_XMLPARSE_H
+#include <xmlparse.h>
+#else
+#include <expat.h>
+#endif
+#endif
+
+#if HAVE_XML2
+#include "fclibxml2.h"
+#endif
+
FcTest *
FcTestCreate (FcQual qual, const FcChar8 *field, FcOp compare, FcExpr *expr)
{
}
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;
}
FcElementAlias,
FcElementBlank,
+ FcElementRescan,
FcElementPrefer,
FcElementAccept,
{ "alias", FcElementAlias },
{ "blank", FcElementBlank },
+ { "rescan", FcElementRescan },
{ "prefer", FcElementPrefer },
{ "accept", FcElementAccept },
XML_Parser parser;
} FcConfigParse;
+typedef enum _FcConfigSeverity {
+ FcSevereInfo, FcSevereWarning, FcSevereError
+} FcConfigSeverity;
+
static void
-FcConfigError (FcConfigParse *parse, char *fmt, ...)
+FcConfigMessage (FcConfigParse *parse, FcConfigSeverity severe, char *fmt, ...)
{
+ char *s = "unknown";
va_list args;
va_start (args, fmt);
+
+ switch (severe) {
+ case FcSevereInfo: s = "info"; break;
+ case FcSevereWarning: s = "warning"; break;
+ case FcSevereError: s = "error"; break;
+ }
if (parse)
{
if (parse->name)
- fprintf (stderr, "Fontconfig error: \"%s\", line %d: ",
+ fprintf (stderr, "Fontconfig %s: \"%s\", line %d: ", s,
parse->name, XML_GetCurrentLineNumber (parse->parser));
else
- fprintf (stderr, "Fontconfig error: line %d: ",
+ fprintf (stderr, "Fontconfig %s: line %d: ", s,
XML_GetCurrentLineNumber (parse->parser));
- parse->error = FcTrue;
+ if (severe >= FcSevereError)
+ parse->error = FcTrue;
}
else
- fprintf (stderr, "Fontconfig error: ");
+ fprintf (stderr, "Fontconfig %s: ", s);
vfprintf (stderr, fmt, args);
fprintf (stderr, "\n");
va_end (args);
{
new->attr = FcConfigSaveAttr (attr);
if (!new->attr)
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
}
else
new->attr = 0;
if (!parse->pstack)
{
- FcConfigError (parse, "mismatching element");
+ FcConfigMessage (parse, FcSevereError, "mismatching element");
return FcFalse;
}
FcVStackClear (parse);
element = FcElementMap (name);
if (element == FcElementUnknown)
- {
- FcConfigError (parse, "unknown element \"%s\"", name);
- return;
- }
+ FcConfigMessage (parse, FcSevereWarning, "unknown element \"%s\"", name);
if (!FcPStackPush (parse, element, attr))
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
return;
{
FcVStack *v = FcVStackFetch (parse, n);
if (v->tag != FcVStackInteger)
- FcConfigError (parse, "non-integer blank");
+ FcConfigMessage (parse, FcSevereError, "non-integer blank");
else
{
if (!parse->config->blanks)
parse->config->blanks = FcBlanksCreate ();
if (!parse->config->blanks)
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
break;
}
}
if (!FcBlanksAdd (parse->config->blanks, v->u.integer))
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
break;
}
}
}
}
+static void
+FcParseRescan (FcConfigParse *parse)
+{
+ int n = FcVStackElements (parse);
+ while (n-- > 0)
+ {
+ FcVStack *v = FcVStackFetch (parse, n);
+ if (v->tag != FcVStackInteger)
+ FcConfigMessage (parse, FcSevereWarning, "non-integer rescan");
+ else
+ parse->config->rescanInterval = v->u.integer;
+ }
+}
+
static void
FcParseInt (FcConfigParse *parse)
{
s = FcStrBufDone (&parse->pstack->str);
if (!s)
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
end = 0;
l = (int) strtol ((char *) s, (char **)&end, 0);
if (end != s + strlen ((char *) s))
- FcConfigError (parse, "\"%s\": not a valid integer", s);
+ FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid integer", s);
else
FcVStackPushInteger (parse, l);
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)
{
s = FcStrBufDone (&parse->pstack->str);
if (!s)
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
end = 0;
- d = strtod ((char *) s, (char **)&end);
+ d = FcStrtod ((char *) s, (char **)&end);
if (end != s + strlen ((char *) s))
- FcConfigError (parse, "\"%s\": not a valid double", s);
+ FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid double", s);
else
FcVStackPushDouble (parse, d);
FcStrFree (s);
s = FcStrBufDone (&parse->pstack->str);
if (!s)
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
if (!FcVStackPushString (parse, tag, s))
while ((vstack = FcVStackPop (parse)))
{
- if (vstack->tag != FcVStackDouble)
- FcConfigError (parse, "non-double matrix element");
- else
- {
- double v = vstack->u._double;
- switch (matrix_state) {
- case m_xx: m.xx = v; break;
- case m_xy: m.xy = v; break;
- case m_yx: m.yx = v; break;
- case m_yy: m.yy = v; break;
- default: break;
- }
- matrix_state--;
+ double v;
+ switch (vstack->tag) {
+ case FcVStackInteger:
+ v = vstack->u.integer;
+ break;
+ case FcVStackDouble:
+ v = vstack->u._double;
+ break;
+ default:
+ FcConfigMessage (parse, FcSevereError, "non-double matrix element");
+ v = 1.0;
+ break;
+ }
+ switch (matrix_state) {
+ case m_xx: m.xx = v; break;
+ case m_xy: m.xy = v; break;
+ case m_yx: m.yx = v; break;
+ case m_yy: m.yy = v; break;
+ default: break;
}
+ matrix_state--;
}
if (matrix_state != m_done)
- FcConfigError (parse, "wrong number of matrix elements");
+ FcConfigMessage (parse, FcSevereError, "wrong number of matrix elements");
else
FcVStackPushMatrix (parse, &m);
}
s = FcStrBufDone (&parse->pstack->str);
if (!s)
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
FcVStackPushBool (parse, FcConfigLexBool (s));
{
if (vstack->tag != FcVStackFamily)
{
- FcConfigError (parse, "non-family");
- break;
+ FcConfigMessage (parse, FcSevereWarning, "non-family");
+ FcVStackDestroy (vstack);
+ continue;
}
left = vstack->u.expr;
vstack->tag = FcVStackNone;
new = FcExprCreateOp (left, FcOpComma, expr);
if (!new)
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
FcExprDestroy (left);
FcExprDestroy (expr);
break;
{
if (!FcVStackPushExpr (parse, tag, expr))
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
if (expr)
FcExprDestroy (expr);
}
s = FcStrBufDone (&parse->pstack->str);
if (!s)
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
expr = FcExprCreateString (s);
static void
FcParseAlias (FcConfigParse *parse)
{
- FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0;
+ FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0;
FcEdit *edit = 0, *next;
FcVStack *vstack;
FcTest *test;
switch (vstack->tag) {
case FcVStackFamily:
if (family)
- FcExprDestroy (family);
- family = vstack->u.expr;
- vstack->tag = FcVStackNone;
+ {
+ new = FcExprCreateOp (vstack->u.expr, FcOpComma, family);
+ if (!new)
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ else
+ family = new;
+ }
+ else
+ new = vstack->u.expr;
+ if (new)
+ {
+ family = new;
+ vstack->tag = FcVStackNone;
+ }
break;
case FcVStackPrefer:
if (prefer)
vstack->tag = FcVStackNone;
break;
default:
- FcConfigError (parse, "bad alias");
+ FcConfigMessage (parse, FcSevereWarning, "bad alias");
break;
}
FcVStackDestroy (vstack);
}
if (!family)
{
- FcConfigError (parse, "missing family in alias");
+ FcConfigMessage (parse, FcSevereError, "missing family in alias");
+ if (prefer)
+ FcExprDestroy (prefer);
+ if (accept)
+ FcExprDestroy (accept);
+ if (def)
+ FcExprDestroy (def);
return;
}
if (prefer)
{
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"),
+ (FcChar8 *) FC_FAMILY,
FcOpEqual,
family);
if (test)
break;
case FcVStackExpr:
expr = vstack->u.expr;
+ vstack->tag = FcVStackNone;
break;
case FcVStackEdit:
break;
new = FcExprCreateOp (left, op, expr);
if (!new)
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
FcExprDestroy (left);
FcExprDestroy (expr);
break;
s = FcStrBufDone (&parse->pstack->str);
if (!s)
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
i = FcConfigGetAttribute (parse, "ignore_missing");
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
{
- FcConfigError (parse, "invalid test qual \"%s\"", qual_string);
+ FcConfigMessage (parse, FcSevereWarning, "invalid test qual \"%s\"", qual_string);
return;
}
}
name = FcConfigGetAttribute (parse, "name");
if (!name)
{
- FcConfigError (parse, "missing test name");
+ FcConfigMessage (parse, FcSevereWarning, "missing test name");
return;
}
compare_string = FcConfigGetAttribute (parse, "compare");
compare = FcConfigLexCompare (compare_string);
if (compare == FcOpInvalid)
{
- FcConfigError (parse, "invalid test compare \"%s\"", compare_string);
+ FcConfigMessage (parse, FcSevereWarning, "invalid test compare \"%s\"", compare_string);
return;
}
}
- expr = FcPopExpr (parse);
+ expr = FcPopExprs (parse, FcOpComma);
if (!expr)
{
- FcConfigError (parse, "missing test expression");
+ FcConfigMessage (parse, FcSevereWarning, "missing test expression");
return;
}
test = FcTestCreate (qual, name, compare, expr);
if (!test)
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
FcVStackPushTest (parse, test);
{
const FcChar8 *name;
const FcChar8 *mode_string;
+ const FcChar8 *binding_string;
FcOp mode;
+ FcValueBinding binding;
FcExpr *expr;
FcEdit *edit;
name = FcConfigGetAttribute (parse, "name");
if (!name)
{
- FcConfigError (parse, "missing edit name");
+ FcConfigMessage (parse, FcSevereWarning, "missing edit name");
return;
}
mode_string = FcConfigGetAttribute (parse, "mode");
if (!mode_string)
- mode = FcOpEqual;
+ mode = FcOpAssign;
else
{
mode = FcConfigLexMode (mode_string);
if (mode == FcOpInvalid)
{
- FcConfigError (parse, "invalid edit mode \"%s\"", mode_string);
+ FcConfigMessage (parse, FcSevereWarning, "invalid edit mode \"%s\"", mode_string);
+ 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
+ {
+ 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)
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
FcExprDestroy (expr);
return;
}
kind = FcMatchFont;
else
{
- FcConfigError (parse, "invalid match target \"%s\"", kind_name);
+ FcConfigMessage (parse, FcSevereWarning, "invalid match target \"%s\"", kind_name);
return;
}
}
vstack->tag = FcVStackNone;
break;
default:
- FcConfigError (parse, "invalid match element");
+ FcConfigMessage (parse, FcSevereWarning, "invalid match element");
break;
}
FcVStackDestroy (vstack);
}
if (!FcConfigAddEdit (parse->config, test, edit, kind))
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
}
static void
data = FcStrBufDone (&parse->pstack->str);
if (!data)
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
break;
}
if (!FcConfigAddDir (parse->config, data))
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
free (data);
break;
case FcElementCache:
data = FcStrBufDone (&parse->pstack->str);
if (!data)
{
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
break;
}
if (!FcConfigSetCache (parse->config, data))
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
free (data);
break;
case FcElementInclude:
case FcElementBlank:
FcParseBlank (parse);
break;
+ case FcElementRescan:
+ FcParseRescan (parse);
+ break;
case FcElementPrefer:
FcParseFamilies (parse, FcVStackPrefer);
if (!parse->pstack)
return;
if (!FcStrBufData (&parse->pstack->str, (FcChar8 *) s, len))
- FcConfigError (parse, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory");
}
static void
FcConfigParse *parse = userData;
if (strcmp ((char *) doctypeName, "fontconfig") != 0)
- FcConfigError (parse, "invalid doctype \"%s\"", doctypeName);
+ FcConfigMessage (parse, FcSevereError, "invalid doctype \"%s\"", doctypeName);
}
static void
filename = FcConfigFilename (name);
if (!filename)
goto bail0;
+
+ if (!FcStrSetAdd (config->configFiles, filename))
+ goto bail0;
+
f = fopen ((char *) filename, "r");
free (filename);
if (!f)
buf = XML_GetBuffer (p, BUFSIZ);
if (!buf)
{
- FcConfigError (&parse, "cannot get parse buffer");
+ FcConfigMessage (&parse, FcSevereError, "cannot get parse buffer");
goto bail3;
}
len = fread (buf, 1, BUFSIZ, f);
if (len < 0)
{
- FcConfigError (&parse, "failed reading config file");
+ FcConfigMessage (&parse, FcSevereError, "failed reading config file");
goto bail3;
}
if (!XML_ParseBuffer (p, len, len == 0))
{
- FcConfigError (&parse, "%s",
+ FcConfigMessage (&parse, FcSevereError, "%s",
XML_ErrorString (XML_GetErrorCode (p)));
goto bail3;
}
if (error && complain)
{
if (name)
- FcConfigError (0, "Cannot load config file \"%s\"", name);
+ FcConfigMessage (0, FcSevereError, "Cannot load config file \"%s\"", name);
else
- FcConfigError (0, "Cannot load default config file");
+ FcConfigMessage (0, FcSevereError, "Cannot load default config file");
return FcFalse;
}
return FcTrue;