/*
- * $RCSId: xc/lib/fontconfig/src/fcxml.c,v 1.21 2002/08/22 18:53:22 keithp Exp $
+ * fontconfig/src/fcxml.c
*
* Copyright © 2002 Keith Packard
*
* PERFORMANCE OF THIS SOFTWARE.
*/
-#include <stdarg.h>
#include "fcint.h"
+#include <fcntl.h>
+#include <stdarg.h>
#include <dirent.h>
-#if ENABLE_LIBXML2
+#ifdef ENABLE_LIBXML2
#include <libxml/parser.h>
if (test->next)
FcTestDestroy (test->next);
FcExprDestroy (test->expr);
- FcStrFree ((FcChar8 *) test->field);
FcMemFree (FC_MEM_TEST, sizeof (FcTest));
free (test);
}
{
FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
e->op = FcOpField;
- e->u.field = (char *) FcStrCopy ((FcChar8 *) field);
+ e->u.object = FcObjectFromName (field);
}
return e;
}
case FcOpBool:
break;
case FcOpField:
- FcStrFree ((FcChar8 *) e->u.field);
break;
case FcOpConst:
FcStrFree (e->u.constant);
{
if (e->next)
FcEditDestroy (e->next);
- FcStrFree ((FcChar8 *) e->field);
if (e->expr)
FcExprDestroy (e->expr);
free (e);
FcElementNone,
FcElementFontconfig,
FcElementDir,
+ FcElementCacheDir,
FcElementCache,
FcElementInclude,
FcElementConfig,
FcElementUnknown
} FcElement;
-static struct {
+static const struct {
const char name[16];
FcElement element;
} fcElementMap[] = {
{ "fontconfig", FcElementFontconfig },
{ "dir", FcElementDir },
+ { "cachedir", FcElementCacheDir },
{ "cache", FcElementCache },
{ "include", FcElementInclude },
{ "config", FcElementConfig },
int integer;
double _double;
FcMatrix *matrix;
- FcBool bool;
+ FcBool bool_;
FcTest *test;
FcQual qual;
{
if (parse->name)
fprintf (stderr, "Fontconfig %s: \"%s\", line %d: ", s,
- parse->name, XML_GetCurrentLineNumber (parse->parser));
+ parse->name, (int)XML_GetCurrentLineNumber (parse->parser));
else
fprintf (stderr, "Fontconfig %s: line %d: ", s,
- XML_GetCurrentLineNumber (parse->parser));
+ (int)XML_GetCurrentLineNumber (parse->parser));
if (severe >= FcSevereError)
parse->error = FcTrue;
}
if ((value == FcTypeLangSet && type == FcTypeString) ||
(value == FcTypeString && type == FcTypeLangSet))
return;
+ if (type == (FcType) -1)
+ return;
FcConfigMessage (parse, FcSevereWarning, "saw %s, expected %s",
FcTypeName (value), FcTypeName (type));
}
const FcObjectType *o;
const FcConstant *c;
+ /* If parsing the expression failed, some nodes may be NULL */
+ if (!expr)
+ return;
+
switch (expr->op) {
case FcOpInteger:
case FcOpDouble:
case FcOpNil:
break;
case FcOpField:
- o = FcNameGetObjectType (expr->u.field);
+ o = FcNameGetObjectType (FcObjectName (expr->u.object));
if (o)
FcTypecheckValue (parse, o->type, type);
break;
if (o)
FcTypecheckValue (parse, o->type, type);
}
+ else
+ FcConfigMessage (parse, FcSevereWarning,
+ "invalid constant used : %s",
+ expr->u.constant);
break;
case FcOpQuest:
FcTypecheckExpr (parse, expr->u.tree.left, FcTypeBool);
test->next = 0;
test->kind = kind;
test->qual = qual;
- test->field = (char *) FcStrCopy (field);
+ test->object = FcObjectFromName ((const char *) field);
test->op = compare;
test->expr = expr;
- o = FcNameGetObjectType (test->field);
+ o = FcNameGetObjectType (FcObjectName (test->object));
if (o)
FcTypecheckExpr (parse, expr, o->type);
}
static FcEdit *
FcEditCreate (FcConfigParse *parse,
- const char *field,
+ FcObject object,
FcOp op,
FcExpr *expr,
FcValueBinding binding)
const FcObjectType *o;
e->next = 0;
- e->field = field; /* already saved in grammar */
+ e->object = object;
e->op = op;
e->expr = expr;
e->binding = binding;
- o = FcNameGetObjectType (e->field);
+ o = FcNameGetObjectType (FcObjectName (e->object));
if (o)
FcTypecheckExpr (parse, expr, o->type);
}
}
static FcBool
-FcVStackPushBool (FcConfigParse *parse, FcBool bool)
+FcVStackPushBool (FcConfigParse *parse, FcBool bool_)
{
FcVStack *vstack = FcVStackCreate ();
if (!vstack)
return FcFalse;
- vstack->u.bool = bool;
+ vstack->u.bool_ = bool_;
vstack->tag = FcVStackBool;
FcVStackPush (parse, vstack);
return FcTrue;
static FcChar8 **
FcConfigSaveAttr (const XML_Char **attr)
{
- int n;
int slen;
int i;
FcChar8 **new;
return 0;
slen = 0;
for (i = 0; attr[i]; i++)
- slen += strlen (attr[i]) + 1;
- n = i;
+ slen += strlen ((char *) attr[i]) + 1;
new = malloc ((i + 1) * sizeof (FcChar8 *) + slen);
if (!new)
return 0;
{
new->attr = FcConfigSaveAttr (attr);
if (!new->attr)
+ {
FcConfigMessage (parse, FcSevereError, "out of memory");
+ FcMemFree (FC_MEM_PSTACK, sizeof (FcPStack));
+ free (new);
+ return FcFalse;
+ }
}
else
new->attr = 0;
return 0;
attrs = parse->pstack->attr;
+ if (!attrs)
+ return 0;
+
while (*attrs)
{
if (!strcmp ((char *) *attrs, attr))
}
static FcBool
-FcConfigLexBool (FcConfigParse *parse, const FcChar8 *bool)
+FcConfigLexBool (FcConfigParse *parse, const FcChar8 *bool_)
{
FcBool result = FcFalse;
- if (!FcNameBool (bool, &result))
+ if (!FcNameBool (bool_, &result))
FcConfigMessage (parse, FcSevereWarning, "\"%s\" is not known boolean",
- bool);
+ bool_);
return result;
}
FcStrFree (s);
}
+static FcBool
+FcConfigLexBinding (FcConfigParse *parse,
+ const FcChar8 *binding_string,
+ FcValueBinding *binding_ret)
+{
+ FcValueBinding 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 binding \"%s\"", binding_string);
+ return FcFalse;
+ }
+ }
+ *binding_ret = binding;
+ return FcTrue;
+}
+
static void
FcParseFamilies (FcConfigParse *parse, FcVStackTag tag)
{
if (!FcVStackPushExpr (parse, tag, expr))
{
FcConfigMessage (parse, FcSevereError, "out of memory");
- if (expr)
- FcExprDestroy (expr);
+ FcExprDestroy (expr);
}
}
}
FcEdit *edit = 0, *next;
FcVStack *vstack;
FcTest *test;
+ FcValueBinding binding;
+ if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding))
+ return;
while ((vstack = FcVStackPop (parse)))
{
switch (vstack->tag) {
if (prefer)
{
edit = FcEditCreate (parse,
- FcConfigSaveField ("family"),
+ FC_FAMILY_OBJECT,
FcOpPrepend,
prefer,
- FcValueBindingWeak);
+ binding);
if (edit)
edit->next = 0;
else
{
next = edit;
edit = FcEditCreate (parse,
- FcConfigSaveField ("family"),
+ FC_FAMILY_OBJECT,
FcOpAppend,
accept,
- FcValueBindingWeak);
+ binding);
if (edit)
edit->next = next;
else
{
next = edit;
edit = FcEditCreate (parse,
- FcConfigSaveField ("family"),
+ FC_FAMILY_OBJECT,
FcOpAppendLast,
def,
- FcValueBindingWeak);
+ binding);
if (edit)
edit->next = next;
else
expr = FcExprCreateMatrix (vstack->u.matrix);
break;
case FcVStackBool:
- expr = FcExprCreateBool (vstack->u.bool);
+ expr = FcExprCreateBool (vstack->u.bool_);
break;
case FcVStackTest:
break;
FcConfigMessage (parse, FcSevereError, "out of memory");
FcExprDestroy (left);
FcExprDestroy (expr);
- break;
+ return 0;
}
expr = new;
}
return FcConfigLexOp (compare, fcCompareOps, NUM_COMPARE_OPS);
}
-
static void
FcParseTest (FcConfigParse *parse)
{
kind = FcMatchPattern;
else if (!strcmp ((char *) kind_string, "font"))
kind = FcMatchFont;
+ else if (!strcmp ((char *) kind_string, "scan"))
+ kind = FcMatchScan;
else if (!strcmp ((char *) kind_string, "default"))
kind = FcMatchDefault;
else
{
const FcChar8 *name;
const FcChar8 *mode_string;
- const FcChar8 *binding_string;
FcOp mode;
FcValueBinding binding;
FcExpr *expr;
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;
- }
- }
+ if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding))
+ return;
+
expr = FcPopBinary (parse, FcOpComma);
- edit = FcEditCreate (parse, (char *) FcStrCopy (name), mode, expr, binding);
+ edit = FcEditCreate (parse, FcObjectFromName ((char *) name),
+ mode, expr, binding);
if (!edit)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
kind = FcMatchPattern;
else if (!strcmp ((char *) kind_name, "font"))
kind = FcMatchFont;
+ else if (!strcmp ((char *) kind_name, "scan"))
+ kind = FcMatchScan;
else
{
FcConfigMessage (parse, FcSevereWarning, "invalid match target \"%s\"", kind_name);
vstack->u.edit->next = edit;
edit = vstack->u.edit;
vstack->tag = FcVStackNone;
+ if (kind == FcMatchScan && edit->object > FC_MAX_BASE_OBJECT)
+ {
+ FcConfigMessage (parse, FcSevereError,
+ "<match target=\"scan\"> cannot edit user-defined object \"%s\"",
+ FcObjectName(edit->object));
+ }
break;
default:
FcConfigMessage (parse, FcSevereWarning, "invalid match element");
value.type = FcTypeMatrix;
break;
case FcVStackBool:
- value.u.b = vstack->u.bool;
+ value.u.b = vstack->u.bool_;
value.type = FcTypeBool;
break;
default:
if (!name)
{
FcConfigMessage (parse, FcSevereWarning, "missing pattern element name");
+ FcPatternDestroy (pattern);
return;
}
if (!FcPatternAdd (pattern, name, value, FcTrue))
{
FcConfigMessage (parse, FcSevereError, "out of memory");
+ FcValueDestroy(value);
break;
}
+ FcValueDestroy(value);
}
FcVStackPushPattern (parse, pattern);
if (!FcPatternAppend (pattern, vstack->u.pattern))
{
FcConfigMessage (parse, FcSevereError, "out of memory");
+ FcPatternDestroy (pattern);
return;
}
break;
break;
}
#ifdef _WIN32
- if (strcmp (data, "WINDOWSFONTDIR") == 0)
+ if (strcmp (data, "CUSTOMFONTDIR") == 0)
+ {
+ char *p;
+ FcStrFree (data);
+ data = malloc (1000);
+ if (!data)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ break;
+ }
+ FcMemAlloc (FC_MEM_STRING, 1000);
+ if(!GetModuleFileName(NULL, data, 1000))
+ {
+ FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
+ FcStrFree (data);
+ break;
+ }
+ p = strrchr (data, '\\');
+ if (p) *p = '\0';
+ strcat (data, "\\fonts");
+ }
+ else if (strcmp (data, "APPSHAREFONTDIR") == 0)
+ {
+ char *p;
+ FcStrFree (data);
+ data = malloc (1000);
+ if (!data)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ break;
+ }
+ FcMemAlloc (FC_MEM_STRING, 1000);
+ if(!GetModuleFileName(NULL, data, 1000))
+ {
+ FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
+ FcStrFree (data);
+ break;
+ }
+ p = strrchr (data, '\\');
+ if (p) *p = '\0';
+ strcat (data, "\\..\\share\\fonts");
+ }
+ else if (strcmp (data, "WINDOWSFONTDIR") == 0)
{
int rc;
FcStrFree (data);
strcat (data, "fonts");
}
#endif
- if (!FcStrUsesHome (data) || FcConfigHome ())
+ if (strlen ((char *) data) == 0)
+ FcConfigMessage (parse, FcSevereWarning, "empty font directory name ignored");
+ else if (!FcStrUsesHome (data) || FcConfigHome ())
{
if (!FcConfigAddDir (parse->config, data))
- FcConfigMessage (parse, FcSevereError, "out of memory");
+ FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", data);
}
FcStrFree (data);
break;
- case FcElementCache:
+ case FcElementCacheDir:
data = FcStrBufDone (&parse->pstack->str);
if (!data)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
break;
}
- if (!FcStrUsesHome (data) || FcConfigHome ())
+#ifdef _WIN32
+ if (strcmp (data, "WINDOWSTEMPDIR_FONTCONFIG_CACHE") == 0)
{
- if (!FcConfigSetCache (parse->config, data))
+ int rc;
+ FcStrFree (data);
+ data = malloc (1000);
+ if (!data)
+ {
FcConfigMessage (parse, FcSevereError, "out of memory");
+ break;
+ }
+ FcMemAlloc (FC_MEM_STRING, 1000);
+ rc = GetTempPath (800, data);
+ if (rc == 0 || rc > 800)
+ {
+ FcConfigMessage (parse, FcSevereError, "GetWindowsDirectory failed");
+ FcStrFree (data);
+ break;
+ }
+ if (data [strlen (data) - 1] != '\\')
+ strcat (data, "\\");
+ strcat (data, "fontconfig\\cache");
+ }
+#endif
+ if (!FcStrUsesHome (data) || FcConfigHome ())
+ {
+ if (!FcConfigAddCacheDir (parse->config, data))
+ FcConfigMessage (parse, FcSevereError, "out of memory; cannot add cache directory %s", data);
+ }
+ FcStrFree (data);
+ break;
+
+ case FcElementCache:
+ data = FcStrBufDone (&parse->pstack->str);
+ if (!data)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ break;
}
+ /* discard this data; no longer used */
FcStrFree (data);
break;
case FcElementInclude:
FcConfigMessage (parse, FcSevereError, "invalid doctype \"%s\"", doctypeName);
}
-#if ENABLE_LIBXML2
+#ifdef ENABLE_LIBXML2
static void
FcInternalSubsetDecl (void *userData,
#endif /* ENABLE_LIBXML2 */
+static int
+FcSortCmpStr (const void *a, const void *b)
+{
+ const FcChar8 *as = *((FcChar8 **) a);
+ const FcChar8 *bs = *((FcChar8 **) b);
+ return FcStrCmp (as, bs);
+}
+
static FcBool
FcConfigParseAndLoadDir (FcConfig *config,
const FcChar8 *name,
{
int i;
qsort (files->strs, files->num, sizeof (FcChar8 *),
- (int (*)(const void *, const void *)) FcStrCmp);
+ (int (*)(const void *, const void *)) FcSortCmpStr);
for (i = 0; ret && i < files->num; i++)
ret = FcConfigParseAndLoad (config, files->strs[i], complain);
}
XML_Parser p;
FcChar8 *filename;
- FILE *f;
+ int fd;
int len;
FcConfigParse parse;
FcBool error = FcTrue;
-#if ENABLE_LIBXML2
+#ifdef ENABLE_LIBXML2
xmlSAXHandler sax;
char buf[BUFSIZ];
#else
if (!filename)
goto bail0;
+ if (FcStrSetMember (config->configFiles, filename))
+ {
+ FcStrFree (filename);
+ return FcTrue;
+ }
+
if (!FcStrSetAdd (config->configFiles, filename))
{
FcStrFree (filename);
if (FcDebug () & FC_DBG_CONFIG)
printf ("\tLoading config file %s\n", filename);
- f = fopen ((char *) filename, "r");
- FcStrFree (filename);
- if (!f)
+ fd = open ((char *) filename, O_RDONLY);
+ if (fd == -1) {
+ FcStrFree (filename);
goto bail0;
+ }
-#if ENABLE_LIBXML2
+#ifdef ENABLE_LIBXML2
memset(&sax, 0, sizeof(sax));
sax.internalSubset = FcInternalSubsetDecl;
sax.endElement = FcEndElement;
sax.characters = FcCharacterData;
- p = xmlCreatePushParserCtxt (&sax, &parse, NULL, 0, filename);
+ p = xmlCreatePushParserCtxt (&sax, &parse, NULL, 0, (const char *) filename);
#else
p = XML_ParserCreate ("UTF-8");
#endif
+ FcStrFree (filename);
if (!p)
goto bail1;
if (!FcConfigInit (&parse, name, config, p))
goto bail2;
-#if !ENABLE_LIBXML2
+#ifndef ENABLE_LIBXML2
XML_SetUserData (p, &parse);
#endif /* ENABLE_LIBXML2 */
do {
-#if !ENABLE_LIBXML2
+#ifndef ENABLE_LIBXML2
buf = XML_GetBuffer (p, BUFSIZ);
if (!buf)
{
goto bail3;
}
#endif
- len = fread (buf, 1, BUFSIZ, f);
+ len = read (fd, buf, BUFSIZ);
if (len < 0)
{
FcConfigMessage (&parse, FcSevereError, "failed reading config file");
goto bail3;
}
-#if ENABLE_LIBXML2
+#ifdef ENABLE_LIBXML2
if (xmlParseChunk (p, buf, len, len == 0))
#else
if (!XML_ParseBuffer (p, len, len == 0))
bail2:
XML_ParserFree (p);
bail1:
- fclose (f);
- f = NULL;
+ close (fd);
+ fd = -1;
bail0:
if (error && complain)
{
}
return FcTrue;
}
+#define __fcxml__
+#include "fcaliastail.h"
+#undef __fcxml__