2 * $XFree86: xc/lib/fontconfig/src/fcxml.c,v 1.10 2002/06/08 17:32:05 keithp Exp $
4 * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
37 #ifndef HAVE_XMLPARSE_H
38 #define HAVE_XMLPARSE_H 0
48 #include "fclibxml2.h"
52 FcTestCreate (FcQual qual, const FcChar8 *field, FcOp compare, FcExpr *expr)
54 FcTest *test = (FcTest *) malloc (sizeof (FcTest));
60 test->field = (char *) FcStrCopy (field);
68 FcTestDestroy (FcTest *test)
71 FcTestDestroy (test->next);
72 FcExprDestroy (test->expr);
73 FcStrFree ((FcChar8 *) test->field);
78 FcExprCreateInteger (int i)
80 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
91 FcExprCreateDouble (double d)
93 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
104 FcExprCreateString (const FcChar8 *s)
106 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
111 e->u.sval = FcStrCopy (s);
117 FcExprCreateMatrix (const FcMatrix *m)
119 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
124 e->u.mval = FcMatrixCopy (m);
130 FcExprCreateBool (FcBool b)
132 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
143 FcExprCreateNil (void)
145 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
155 FcExprCreateField (const char *field)
157 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
162 e->u.field = (char *) FcStrCopy ((FcChar8 *) field);
168 FcExprCreateConst (const FcChar8 *constant)
170 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
175 e->u.constant = FcStrCopy (constant);
181 FcExprCreateOp (FcExpr *left, FcOp op, FcExpr *right)
183 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
188 e->u.tree.left = left;
189 e->u.tree.right = right;
195 FcExprDestroy (FcExpr *e)
203 FcStrFree (e->u.sval);
206 FcMatrixFree (e->u.mval);
209 FcCharSetDestroy (e->u.cval);
214 FcStrFree ((FcChar8 *) e->u.field);
217 FcStrFree (e->u.constant);
220 case FcOpAssignReplace:
222 case FcOpPrependFirst:
241 FcExprDestroy (e->u.tree.right);
244 FcExprDestroy (e->u.tree.left);
254 FcEditCreate (const char *field, FcOp op, FcExpr *expr)
256 FcEdit *e = (FcEdit *) malloc (sizeof (FcEdit));
261 e->field = field; /* already saved in grammar */
269 FcEditDestroy (FcEdit *e)
272 FcEditDestroy (e->next);
273 FcStrFree ((FcChar8 *) e->field);
275 FcExprDestroy (e->expr);
279 FcConfigSaveField (const char *field)
281 return (char *) FcStrCopy ((FcChar8 *) field);
284 typedef enum _FcElement {
330 FcElementMap (const XML_Char *name)
336 { "fontconfig", FcElementFontconfig },
337 { "dir", FcElementDir },
338 { "cache", FcElementCache },
339 { "include", FcElementInclude },
340 { "config", FcElementConfig },
341 { "match", FcElementMatch },
342 { "alias", FcElementAlias },
344 { "blank", FcElementBlank },
345 { "rescan", FcElementRescan },
347 { "prefer", FcElementPrefer },
348 { "accept", FcElementAccept },
349 { "default", FcElementDefault },
350 { "family", FcElementFamily },
352 { "test", FcElementTest },
353 { "edit", FcElementEdit },
354 { "int", FcElementInt },
355 { "double", FcElementDouble },
356 { "string", FcElementString },
357 { "matrix", FcElementMatrix },
358 { "bool", FcElementBool },
359 { "charset", FcElementCharset },
360 { "name", FcElementName },
361 { "const", FcElementConst },
362 { "or", FcElementOr },
363 { "and", FcElementAnd },
364 { "eq", FcElementEq },
365 { "not_eq", FcElementNotEq },
366 { "less", FcElementLess },
367 { "less_eq", FcElementLessEq },
368 { "more", FcElementMore },
369 { "more_eq", FcElementMoreEq },
370 { "plus", FcElementPlus },
371 { "minus", FcElementMinus },
372 { "times", FcElementTimes },
373 { "divide", FcElementDivide },
374 { "not", FcElementNot },
375 { "if", FcElementIf },
381 for (i = 0; fcElementMap[i].name; i++)
382 if (!strcmp ((char *) name, fcElementMap[i].name))
383 return fcElementMap[i].element;
384 return FcElementUnknown;
387 typedef struct _FcPStack {
388 struct _FcPStack *prev;
394 typedef enum _FcVStackTag {
416 typedef struct _FcVStack {
417 struct _FcVStack *prev;
418 FcPStack *pstack; /* related parse element */
436 typedef struct _FcConfigParse {
445 typedef enum _FcConfigSeverity {
446 FcSevereInfo, FcSevereWarning, FcSevereError
450 FcConfigMessage (FcConfigParse *parse, FcConfigSeverity severe, char *fmt, ...)
455 va_start (args, fmt);
458 case FcSevereInfo: s = "info"; break;
459 case FcSevereWarning: s = "warning"; break;
460 case FcSevereError: s = "error"; break;
465 fprintf (stderr, "Fontconfig %s: \"%s\", line %d: ", s,
466 parse->name, XML_GetCurrentLineNumber (parse->parser));
468 fprintf (stderr, "Fontconfig %s: line %d: ", s,
469 XML_GetCurrentLineNumber (parse->parser));
470 if (severe >= FcSevereError)
471 parse->error = FcTrue;
474 fprintf (stderr, "Fontconfig %s: ", s);
475 vfprintf (stderr, fmt, args);
476 fprintf (stderr, "\n");
481 FcVStackPush (FcConfigParse *parse, FcVStack *vstack)
483 vstack->prev = parse->vstack;
484 vstack->pstack = parse->pstack ? parse->pstack->prev : 0;
485 parse->vstack = vstack;
489 FcVStackCreate (void)
493 new = malloc (sizeof (FcVStack));
496 new->tag = FcVStackNone;
502 FcVStackDestroy (FcVStack *vstack)
506 for (; vstack; vstack = prev)
509 switch (vstack->tag) {
515 case FcVStackConstant:
516 FcStrFree (vstack->u.string);
518 case FcVStackInteger:
522 FcMatrixFree (vstack->u.matrix);
527 FcTestDestroy (vstack->u.test);
532 case FcVStackDefault:
533 FcExprDestroy (vstack->u.expr);
536 FcEditDestroy (vstack->u.edit);
544 FcVStackPushString (FcConfigParse *parse, FcVStackTag tag, FcChar8 *string)
546 FcVStack *vstack = FcVStackCreate ();
549 vstack->u.string = string;
551 FcVStackPush (parse, vstack);
556 FcVStackPushInteger (FcConfigParse *parse, int integer)
558 FcVStack *vstack = FcVStackCreate ();
561 vstack->u.integer = integer;
562 vstack->tag = FcVStackInteger;
563 FcVStackPush (parse, vstack);
568 FcVStackPushDouble (FcConfigParse *parse, double _double)
570 FcVStack *vstack = FcVStackCreate ();
573 vstack->u._double = _double;
574 vstack->tag = FcVStackDouble;
575 FcVStackPush (parse, vstack);
580 FcVStackPushMatrix (FcConfigParse *parse, FcMatrix *matrix)
582 FcVStack *vstack = FcVStackCreate ();
585 matrix = FcMatrixCopy (matrix);
588 FcVStackDestroy (vstack);
591 vstack->u.matrix = matrix;
592 vstack->tag = FcVStackMatrix;
593 FcVStackPush (parse, vstack);
598 FcVStackPushBool (FcConfigParse *parse, FcBool bool)
600 FcVStack *vstack = FcVStackCreate ();
603 vstack->u.bool = bool;
604 vstack->tag = FcVStackBool;
605 FcVStackPush (parse, vstack);
610 FcVStackPushTest (FcConfigParse *parse, FcTest *test)
612 FcVStack *vstack = FcVStackCreate ();
615 vstack->u.test = test;
616 vstack->tag = FcVStackTest;
617 FcVStackPush (parse, vstack);
622 FcVStackPushExpr (FcConfigParse *parse, FcVStackTag tag, FcExpr *expr)
624 FcVStack *vstack = FcVStackCreate ();
627 vstack->u.expr = expr;
629 FcVStackPush (parse, vstack);
634 FcVStackPushEdit (FcConfigParse *parse, FcEdit *edit)
636 FcVStack *vstack = FcVStackCreate ();
639 vstack->u.edit = edit;
640 vstack->tag = FcVStackEdit;
641 FcVStackPush (parse, vstack);
646 FcVStackFetch (FcConfigParse *parse, int off)
650 for (vstack = parse->vstack; vstack && off-- > 0; vstack = vstack->prev);
655 FcVStackClear (FcConfigParse *parse)
657 while (parse->vstack && parse->vstack->pstack == parse->pstack)
659 FcVStack *vstack = parse->vstack;
660 parse->vstack = vstack->prev;
662 FcVStackDestroy (vstack);
667 FcVStackPop (FcConfigParse *parse)
669 FcVStack *vstack = parse->vstack;
671 if (!vstack || vstack->pstack != parse->pstack)
673 parse->vstack = vstack->prev;
679 FcVStackElements (FcConfigParse *parse)
682 FcVStack *vstack = parse->vstack;
683 while (vstack && vstack->pstack == parse->pstack)
686 vstack = vstack->prev;
692 FcConfigSaveAttr (const XML_Char **attr)
703 for (i = 0; attr[i]; i++)
704 slen += strlen (attr[i]) + 1;
706 new = malloc ((i + 1) * sizeof (FcChar8 *) + slen);
709 s = (FcChar8 *) (new + (i + 1));
710 for (i = 0; attr[i]; i++)
713 strcpy ((char *) s, (char *) attr[i]);
714 s += strlen ((char *) s) + 1;
721 FcPStackPush (FcConfigParse *parse, FcElement element, const XML_Char **attr)
723 FcPStack *new = malloc (sizeof (FcPStack));
727 new->prev = parse->pstack;
728 new->element = element;
731 new->attr = FcConfigSaveAttr (attr);
733 FcConfigMessage (parse, FcSevereError, "out of memory");
737 FcStrBufInit (&new->str, 0, 0);
743 FcPStackPop (FcConfigParse *parse)
749 FcConfigMessage (parse, FcSevereError, "mismatching element");
752 FcVStackClear (parse);
754 parse->pstack = old->prev;
755 FcStrBufDestroy (&old->str);
763 FcConfigInit (FcConfigParse *parse, const FcChar8 *name, FcConfig *config, XML_Parser parser)
767 parse->error = FcFalse;
769 parse->config = config;
770 parse->parser = parser;
775 FcConfigCleanup (FcConfigParse *parse)
777 while (parse->pstack)
781 static const FcChar8 *
782 FcConfigGetAttribute (FcConfigParse *parse, char *attr)
788 attrs = parse->pstack->attr;
791 if (!strcmp ((char *) *attrs, attr))
799 FcStartElement(void *userData, const XML_Char *name, const XML_Char **attr)
801 FcConfigParse *parse = userData;
804 element = FcElementMap (name);
805 if (element == FcElementUnknown)
806 FcConfigMessage (parse, FcSevereWarning, "unknown element \"%s\"", name);
808 if (!FcPStackPush (parse, element, attr))
810 FcConfigMessage (parse, FcSevereError, "out of memory");
817 FcParseBlank (FcConfigParse *parse)
819 int n = FcVStackElements (parse);
822 FcVStack *v = FcVStackFetch (parse, n);
823 if (v->tag != FcVStackInteger)
824 FcConfigMessage (parse, FcSevereError, "non-integer blank");
827 if (!parse->config->blanks)
829 parse->config->blanks = FcBlanksCreate ();
830 if (!parse->config->blanks)
832 FcConfigMessage (parse, FcSevereError, "out of memory");
836 if (!FcBlanksAdd (parse->config->blanks, v->u.integer))
838 FcConfigMessage (parse, FcSevereError, "out of memory");
846 FcParseRescan (FcConfigParse *parse)
848 int n = FcVStackElements (parse);
851 FcVStack *v = FcVStackFetch (parse, n);
852 if (v->tag != FcVStackInteger)
853 FcConfigMessage (parse, FcSevereWarning, "non-integer rescan");
855 parse->config->rescanInterval = v->u.integer;
860 FcParseInt (FcConfigParse *parse)
867 s = FcStrBufDone (&parse->pstack->str);
870 FcConfigMessage (parse, FcSevereError, "out of memory");
874 l = (int) strtol ((char *) s, (char **)&end, 0);
875 if (end != s + strlen ((char *) s))
876 FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid integer", s);
878 FcVStackPushInteger (parse, l);
883 FcParseDouble (FcConfigParse *parse)
890 s = FcStrBufDone (&parse->pstack->str);
893 FcConfigMessage (parse, FcSevereError, "out of memory");
897 d = strtod ((char *) s, (char **)&end);
898 if (end != s + strlen ((char *) s))
899 FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid double", s);
901 FcVStackPushDouble (parse, d);
906 FcParseString (FcConfigParse *parse, FcVStackTag tag)
912 s = FcStrBufDone (&parse->pstack->str);
915 FcConfigMessage (parse, FcSevereError, "out of memory");
918 if (!FcVStackPushString (parse, tag, s))
923 FcParseMatrix (FcConfigParse *parse)
926 enum { m_done, m_xx, m_xy, m_yx, m_yy } matrix_state = m_yy;
929 while ((vstack = FcVStackPop (parse)))
932 switch (vstack->tag) {
933 case FcVStackInteger:
934 v = vstack->u.integer;
937 v = vstack->u._double;
940 FcConfigMessage (parse, FcSevereError, "non-double matrix element");
944 switch (matrix_state) {
945 case m_xx: m.xx = v; break;
946 case m_xy: m.xy = v; break;
947 case m_yx: m.yx = v; break;
948 case m_yy: m.yy = v; break;
953 if (matrix_state != m_done)
954 FcConfigMessage (parse, FcSevereError, "wrong number of matrix elements");
956 FcVStackPushMatrix (parse, &m);
960 FcConfigLexBool (const FcChar8 *bool)
962 if (*bool == 't' || *bool == 'T')
964 if (*bool == 'y' || *bool == 'Y')
972 FcParseBool (FcConfigParse *parse)
978 s = FcStrBufDone (&parse->pstack->str);
981 FcConfigMessage (parse, FcSevereError, "out of memory");
984 FcVStackPushBool (parse, FcConfigLexBool (s));
989 FcParseFamilies (FcConfigParse *parse, FcVStackTag tag)
992 FcExpr *left, *expr = 0, *new;
994 while ((vstack = FcVStackPop (parse)))
996 if (vstack->tag != FcVStackFamily)
998 FcConfigMessage (parse, FcSevereWarning, "non-family");
999 FcVStackDestroy (vstack);
1002 left = vstack->u.expr;
1003 vstack->tag = FcVStackNone;
1004 FcVStackDestroy (vstack);
1007 new = FcExprCreateOp (left, FcOpComma, expr);
1010 FcConfigMessage (parse, FcSevereError, "out of memory");
1011 FcExprDestroy (left);
1012 FcExprDestroy (expr);
1022 if (!FcVStackPushExpr (parse, tag, expr))
1024 FcConfigMessage (parse, FcSevereError, "out of memory");
1026 FcExprDestroy (expr);
1032 FcParseFamily (FcConfigParse *parse)
1039 s = FcStrBufDone (&parse->pstack->str);
1042 FcConfigMessage (parse, FcSevereError, "out of memory");
1045 expr = FcExprCreateString (s);
1048 FcVStackPushExpr (parse, FcVStackFamily, expr);
1052 FcParseAlias (FcConfigParse *parse)
1054 FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0;
1055 FcEdit *edit = 0, *next;
1059 while ((vstack = FcVStackPop (parse)))
1061 switch (vstack->tag) {
1062 case FcVStackFamily:
1065 new = FcExprCreateOp (vstack->u.expr, FcOpComma, family);
1067 FcConfigMessage (parse, FcSevereError, "out of memory");
1072 new = vstack->u.expr;
1076 vstack->tag = FcVStackNone;
1079 case FcVStackPrefer:
1081 FcExprDestroy (prefer);
1082 prefer = vstack->u.expr;
1083 vstack->tag = FcVStackNone;
1085 case FcVStackAccept:
1087 FcExprDestroy (accept);
1088 accept = vstack->u.expr;
1089 vstack->tag = FcVStackNone;
1091 case FcVStackDefault:
1093 FcExprDestroy (def);
1094 def = vstack->u.expr;
1095 vstack->tag = FcVStackNone;
1098 FcConfigMessage (parse, FcSevereWarning, "bad alias");
1101 FcVStackDestroy (vstack);
1105 FcConfigMessage (parse, FcSevereError, "missing family in alias");
1107 FcExprDestroy (prefer);
1109 FcExprDestroy (accept);
1111 FcExprDestroy (def);
1116 edit = FcEditCreate (FcConfigSaveField ("family"),
1122 FcExprDestroy (prefer);
1127 edit = FcEditCreate (FcConfigSaveField ("family"),
1133 FcExprDestroy (accept);
1138 edit = FcEditCreate (FcConfigSaveField ("family"),
1144 FcExprDestroy (def);
1148 test = FcTestCreate (FcQualAny,
1149 (FcChar8 *) FC_FAMILY,
1153 if (!FcConfigAddEdit (parse->config, test, edit, FcMatchPattern))
1154 FcTestDestroy (test);
1157 FcExprDestroy (family);
1161 FcPopExpr (FcConfigParse *parse)
1163 FcVStack *vstack = FcVStackPop (parse);
1167 switch (vstack->tag) {
1170 case FcVStackString:
1171 case FcVStackFamily:
1172 expr = FcExprCreateString (vstack->u.string);
1175 expr = FcExprCreateField ((char *) vstack->u.string);
1177 case FcVStackConstant:
1178 expr = FcExprCreateConst (vstack->u.string);
1180 case FcVStackPrefer:
1181 case FcVStackAccept:
1182 case FcVStackDefault:
1183 expr = vstack->u.expr;
1184 vstack->tag = FcVStackNone;
1186 case FcVStackInteger:
1187 expr = FcExprCreateInteger (vstack->u.integer);
1189 case FcVStackDouble:
1190 expr = FcExprCreateDouble (vstack->u._double);
1192 case FcVStackMatrix:
1193 expr = FcExprCreateMatrix (vstack->u.matrix);
1196 expr = FcExprCreateBool (vstack->u.bool);
1201 expr = vstack->u.expr;
1202 vstack->tag = FcVStackNone;
1207 FcVStackDestroy (vstack);
1212 FcPopExprs (FcConfigParse *parse, FcOp op)
1214 FcExpr *left, *expr = 0, *new;
1216 while ((left = FcPopExpr (parse)))
1220 new = FcExprCreateOp (left, op, expr);
1223 FcConfigMessage (parse, FcSevereError, "out of memory");
1224 FcExprDestroy (left);
1225 FcExprDestroy (expr);
1237 FcParseExpr (FcConfigParse *parse, FcOp op)
1239 FcExpr *expr = FcPopExprs (parse, op);
1241 FcVStackPushExpr (parse, FcVStackExpr, expr);
1245 FcParseInclude (FcConfigParse *parse)
1249 FcBool ignore_missing = FcFalse;
1251 s = FcStrBufDone (&parse->pstack->str);
1254 FcConfigMessage (parse, FcSevereError, "out of memory");
1257 i = FcConfigGetAttribute (parse, "ignore_missing");
1258 if (i && FcConfigLexBool ((FcChar8 *) i) == FcTrue)
1259 ignore_missing = FcTrue;
1260 if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing))
1261 parse->error = FcTrue;
1265 typedef struct _FcOpMap {
1271 FcConfigLexOp (const FcChar8 *op, const FcOpMap *map, int nmap)
1275 for (i = 0; i < nmap; i++)
1276 if (!strcmp ((char *) op, map[i].name))
1281 static const FcOpMap fcCompareOps[] = {
1282 { "eq", FcOpEqual },
1283 { "not_eq", FcOpNotEqual },
1284 { "less", FcOpLess },
1285 { "less_eq", FcOpLessEqual },
1286 { "more", FcOpMore },
1287 { "more_eq", FcOpMoreEqual }
1290 #define NUM_COMPARE_OPS (sizeof fcCompareOps / sizeof fcCompareOps[0])
1293 FcConfigLexCompare (const FcChar8 *compare)
1295 return FcConfigLexOp (compare, fcCompareOps, NUM_COMPARE_OPS);
1300 FcParseTest (FcConfigParse *parse)
1302 const FcChar8 *qual_string;
1304 const FcChar8 *name;
1305 const FcChar8 *compare_string;
1310 qual_string = FcConfigGetAttribute (parse, "qual");
1315 if (!strcmp ((char *) qual_string, "any"))
1317 else if (!strcmp ((char *) qual_string, "all"))
1321 FcConfigMessage (parse, FcSevereWarning, "invalid test qual \"%s\"", qual_string);
1325 name = FcConfigGetAttribute (parse, "name");
1328 FcConfigMessage (parse, FcSevereWarning, "missing test name");
1329 name = (FcChar8 *) FC_FAMILY;
1331 compare_string = FcConfigGetAttribute (parse, "compare");
1332 if (!compare_string)
1333 compare = FcOpEqual;
1336 compare = FcConfigLexCompare (compare_string);
1337 if (compare == FcOpInvalid)
1339 FcConfigMessage (parse, FcSevereWarning, "invalid test compare \"%s\"", compare_string);
1340 compare = FcOpEqual;
1343 expr = FcPopExprs (parse, FcOpComma);
1346 FcConfigMessage (parse, FcSevereWarning, "missing test expression");
1349 test = FcTestCreate (qual, name, compare, expr);
1352 FcConfigMessage (parse, FcSevereError, "out of memory");
1355 FcVStackPushTest (parse, test);
1358 static const FcOpMap fcModeOps[] = {
1359 { "assign", FcOpAssign },
1360 { "assign_replace", FcOpAssignReplace },
1361 { "prepend", FcOpPrepend },
1362 { "prepend_first", FcOpPrependFirst },
1363 { "append", FcOpAppend },
1364 { "append_last", FcOpAppendLast },
1367 #define NUM_MODE_OPS (sizeof fcModeOps / sizeof fcModeOps[0])
1370 FcConfigLexMode (const FcChar8 *mode)
1372 return FcConfigLexOp (mode, fcModeOps, NUM_MODE_OPS);
1376 FcParseEdit (FcConfigParse *parse)
1378 const FcChar8 *name;
1379 const FcChar8 *mode_string;
1384 name = FcConfigGetAttribute (parse, "name");
1387 FcConfigMessage (parse, FcSevereWarning, "missing edit name");
1388 name = (FcChar8 *) FC_FAMILY;
1390 mode_string = FcConfigGetAttribute (parse, "mode");
1395 mode = FcConfigLexMode (mode_string);
1396 if (mode == FcOpInvalid)
1398 FcConfigMessage (parse, FcSevereWarning, "invalid edit mode \"%s\"", mode_string);
1402 expr = FcPopExprs (parse, FcOpComma);
1403 edit = FcEditCreate ((char *) FcStrCopy (name), mode, expr);
1406 FcConfigMessage (parse, FcSevereError, "out of memory");
1407 FcExprDestroy (expr);
1410 if (!FcVStackPushEdit (parse, edit))
1411 FcEditDestroy (edit);
1415 FcParseMatch (FcConfigParse *parse)
1417 const FcChar8 *kind_name;
1423 kind_name = FcConfigGetAttribute (parse, "target");
1425 kind = FcMatchPattern;
1428 if (!strcmp ((char *) kind_name, "pattern"))
1429 kind = FcMatchPattern;
1430 else if (!strcmp ((char *) kind_name, "font"))
1434 FcConfigMessage (parse, FcSevereWarning, "invalid match target \"%s\"", kind_name);
1435 kind = FcMatchPattern;
1438 while ((vstack = FcVStackPop (parse)))
1440 switch (vstack->tag) {
1442 vstack->u.test->next = test;
1443 test = vstack->u.test;
1444 vstack->tag = FcVStackNone;
1447 vstack->u.edit->next = edit;
1448 edit = vstack->u.edit;
1449 vstack->tag = FcVStackNone;
1452 FcConfigMessage (parse, FcSevereWarning, "invalid match element");
1455 FcVStackDestroy (vstack);
1457 if (!FcConfigAddEdit (parse->config, test, edit, kind))
1458 FcConfigMessage (parse, FcSevereError, "out of memory");
1462 FcEndElement(void *userData, const XML_Char *name)
1464 FcConfigParse *parse = userData;
1469 switch (parse->pstack->element) {
1472 case FcElementFontconfig:
1475 data = FcStrBufDone (&parse->pstack->str);
1478 FcConfigMessage (parse, FcSevereError, "out of memory");
1481 if (!FcConfigAddDir (parse->config, data))
1482 FcConfigMessage (parse, FcSevereError, "out of memory");
1485 case FcElementCache:
1486 data = FcStrBufDone (&parse->pstack->str);
1489 FcConfigMessage (parse, FcSevereError, "out of memory");
1492 if (!FcConfigSetCache (parse->config, data))
1493 FcConfigMessage (parse, FcSevereError, "out of memory");
1496 case FcElementInclude:
1497 FcParseInclude (parse);
1499 case FcElementConfig:
1501 case FcElementMatch:
1502 FcParseMatch (parse);
1504 case FcElementAlias:
1505 FcParseAlias (parse);
1508 case FcElementBlank:
1509 FcParseBlank (parse);
1511 case FcElementRescan:
1512 FcParseRescan (parse);
1515 case FcElementPrefer:
1516 FcParseFamilies (parse, FcVStackPrefer);
1518 case FcElementAccept:
1519 FcParseFamilies (parse, FcVStackAccept);
1521 case FcElementDefault:
1522 FcParseFamilies (parse, FcVStackDefault);
1524 case FcElementFamily:
1525 FcParseFamily (parse);
1529 FcParseTest (parse);
1532 FcParseEdit (parse);
1538 case FcElementDouble:
1539 FcParseDouble (parse);
1541 case FcElementString:
1542 FcParseString (parse, FcVStackString);
1544 case FcElementMatrix:
1545 FcParseMatrix (parse);
1548 FcParseBool (parse);
1550 case FcElementCharset:
1551 /* FcParseCharset (parse); */
1555 FcParseString (parse, FcVStackField);
1557 case FcElementConst:
1558 FcParseString (parse, FcVStackConstant);
1561 FcParseExpr (parse, FcOpOr);
1564 FcParseExpr (parse, FcOpAnd);
1567 FcParseExpr (parse, FcOpEqual);
1569 case FcElementNotEq:
1570 FcParseExpr (parse, FcOpNotEqual);
1573 FcParseExpr (parse, FcOpLess);
1575 case FcElementLessEq:
1576 FcParseExpr (parse, FcOpLessEqual);
1579 FcParseExpr (parse, FcOpMore);
1581 case FcElementMoreEq:
1582 FcParseExpr (parse, FcOpMoreEqual);
1585 FcParseExpr (parse, FcOpPlus);
1587 case FcElementMinus:
1588 FcParseExpr (parse, FcOpMinus);
1590 case FcElementTimes:
1591 FcParseExpr (parse, FcOpTimes);
1593 case FcElementDivide:
1594 FcParseExpr (parse, FcOpDivide);
1597 FcParseExpr (parse, FcOpNot);
1600 FcParseExpr (parse, FcOpQuest);
1602 case FcElementUnknown:
1605 (void) FcPStackPop (parse);
1609 FcCharacterData (void *userData, const XML_Char *s, int len)
1611 FcConfigParse *parse = userData;
1615 if (!FcStrBufData (&parse->pstack->str, (FcChar8 *) s, len))
1616 FcConfigMessage (parse, FcSevereError, "out of memory");
1620 FcStartDoctypeDecl (void *userData,
1621 const XML_Char *doctypeName,
1622 const XML_Char *sysid,
1623 const XML_Char *pubid,
1624 int has_internal_subset)
1626 FcConfigParse *parse = userData;
1628 if (strcmp ((char *) doctypeName, "fontconfig") != 0)
1629 FcConfigMessage (parse, FcSevereError, "invalid doctype \"%s\"", doctypeName);
1633 FcEndDoctypeDecl (void *userData)
1638 FcConfigParseAndLoad (FcConfig *config,
1639 const FcChar8 *name,
1648 FcConfigParse parse;
1649 FcBool error = FcTrue;
1651 filename = FcConfigFilename (name);
1654 f = fopen ((char *) filename, "r");
1659 p = XML_ParserCreate ("UTF-8");
1663 if (!FcConfigInit (&parse, name, config, p))
1666 XML_SetUserData (p, &parse);
1668 XML_SetDoctypeDeclHandler (p, FcStartDoctypeDecl, FcEndDoctypeDecl);
1669 XML_SetElementHandler (p, FcStartElement, FcEndElement);
1670 XML_SetCharacterDataHandler (p, FcCharacterData);
1673 buf = XML_GetBuffer (p, BUFSIZ);
1676 FcConfigMessage (&parse, FcSevereError, "cannot get parse buffer");
1679 len = fread (buf, 1, BUFSIZ, f);
1682 FcConfigMessage (&parse, FcSevereError, "failed reading config file");
1685 if (!XML_ParseBuffer (p, len, len == 0))
1687 FcConfigMessage (&parse, FcSevereError, "%s",
1688 XML_ErrorString (XML_GetErrorCode (p)));
1692 error = parse.error;
1694 FcConfigCleanup (&parse);
1700 if (error && complain)
1703 FcConfigMessage (0, FcSevereError, "Cannot load config file \"%s\"", name);
1705 FcConfigMessage (0, FcSevereError, "Cannot load default config file");