]>
git.wh0rd.org - fontconfig.git/blob - src/fcxml.c
2 * fontconfig/src/fcxml.c
4 * Copyright © 2002 Keith Packard
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.
32 #include <libxml/parser.h>
34 #define XML_Char xmlChar
35 #define XML_Parser xmlParserCtxtPtr
36 #define XML_ParserFree xmlFreeParserCtxt
37 #define XML_GetCurrentLineNumber xmlSAX2GetLineNumber
38 #define XML_GetErrorCode xmlCtxtGetLastError
39 #define XML_ErrorString(Error) (Error)->message
41 #else /* ENABLE_LIBXML2 */
43 #ifndef HAVE_XMLPARSE_H
44 #define HAVE_XMLPARSE_H 0
53 #endif /* ENABLE_LIBXML2 */
63 FcTestDestroy (FcTest
*test
)
66 FcTestDestroy (test
->next
);
67 FcExprDestroy (test
->expr
);
68 FcMemFree (FC_MEM_TEST
, sizeof (FcTest
));
73 FcExprCreateInteger (int i
)
75 FcExpr
*e
= (FcExpr
*) malloc (sizeof (FcExpr
));
79 FcMemAlloc (FC_MEM_EXPR
, sizeof (FcExpr
));
87 FcExprCreateDouble (double d
)
89 FcExpr
*e
= (FcExpr
*) malloc (sizeof (FcExpr
));
93 FcMemAlloc (FC_MEM_EXPR
, sizeof (FcExpr
));
101 FcExprCreateString (const FcChar8
*s
)
103 FcExpr
*e
= (FcExpr
*) malloc (sizeof (FcExpr
));
107 FcMemAlloc (FC_MEM_EXPR
, sizeof (FcExpr
));
109 e
->u
.sval
= FcStrCopy (s
);
115 FcExprCreateMatrix (const FcMatrix
*m
)
117 FcExpr
*e
= (FcExpr
*) malloc (sizeof (FcExpr
));
121 FcMemAlloc (FC_MEM_EXPR
, sizeof (FcExpr
));
123 e
->u
.mval
= FcMatrixCopy (m
);
129 FcExprCreateBool (FcBool b
)
131 FcExpr
*e
= (FcExpr
*) malloc (sizeof (FcExpr
));
135 FcMemAlloc (FC_MEM_EXPR
, sizeof (FcExpr
));
143 FcExprCreateNil (void)
145 FcExpr
*e
= (FcExpr
*) malloc (sizeof (FcExpr
));
149 FcMemAlloc (FC_MEM_EXPR
, sizeof (FcExpr
));
156 FcExprCreateField (const char *field
)
158 FcExpr
*e
= (FcExpr
*) malloc (sizeof (FcExpr
));
162 FcMemAlloc (FC_MEM_EXPR
, sizeof (FcExpr
));
164 e
->u
.object
= FcObjectFromName (field
);
170 FcExprCreateConst (const FcChar8
*constant
)
172 FcExpr
*e
= (FcExpr
*) malloc (sizeof (FcExpr
));
176 FcMemAlloc (FC_MEM_EXPR
, sizeof (FcExpr
));
178 e
->u
.constant
= FcStrCopy (constant
);
184 FcExprCreateOp (FcExpr
*left
, FcOp op
, FcExpr
*right
)
186 FcExpr
*e
= (FcExpr
*) malloc (sizeof (FcExpr
));
190 FcMemAlloc (FC_MEM_EXPR
, sizeof (FcExpr
));
192 e
->u
.tree
.left
= left
;
193 e
->u
.tree
.right
= right
;
199 FcExprDestroy (FcExpr
*e
)
209 FcStrFree (e
->u
.sval
);
212 FcMatrixFree (e
->u
.mval
);
215 FcCharSetDestroy (e
->u
.cval
);
222 FcStrFree (e
->u
.constant
);
225 case FcOpAssignReplace
:
227 case FcOpPrependFirst
:
241 case FcOpNotContains
:
248 FcExprDestroy (e
->u
.tree
.right
);
255 FcExprDestroy (e
->u
.tree
.left
);
261 FcMemFree (FC_MEM_EXPR
, sizeof (FcExpr
));
266 FcEditDestroy (FcEdit
*e
)
269 FcEditDestroy (e
->next
);
271 FcExprDestroy (e
->expr
);
276 FcConfigSaveField (const char *field
)
278 return (char *) FcStrCopy ((FcChar8
*) field
);
281 typedef enum _FcElement
{
326 FcElementNotContains
,
340 static const struct {
344 { "fontconfig", FcElementFontconfig
},
345 { "dir", FcElementDir
},
346 { "cachedir", FcElementCacheDir
},
347 { "cache", FcElementCache
},
348 { "include", FcElementInclude
},
349 { "config", FcElementConfig
},
350 { "match", FcElementMatch
},
351 { "alias", FcElementAlias
},
353 { "blank", FcElementBlank
},
354 { "rescan", FcElementRescan
},
356 { "prefer", FcElementPrefer
},
357 { "accept", FcElementAccept
},
358 { "default", FcElementDefault
},
359 { "family", FcElementFamily
},
361 { "selectfont", FcElementSelectfont
},
362 { "acceptfont", FcElementAcceptfont
},
363 { "rejectfont", FcElementRejectfont
},
364 { "glob", FcElementGlob
},
365 { "pattern", FcElementPattern
},
366 { "patelt", FcElementPatelt
},
368 { "test", FcElementTest
},
369 { "edit", FcElementEdit
},
370 { "int", FcElementInt
},
371 { "double", FcElementDouble
},
372 { "string", FcElementString
},
373 { "matrix", FcElementMatrix
},
374 { "bool", FcElementBool
},
375 { "charset", FcElementCharset
},
376 { "name", FcElementName
},
377 { "const", FcElementConst
},
378 { "or", FcElementOr
},
379 { "and", FcElementAnd
},
380 { "eq", FcElementEq
},
381 { "not_eq", FcElementNotEq
},
382 { "less", FcElementLess
},
383 { "less_eq", FcElementLessEq
},
384 { "more", FcElementMore
},
385 { "more_eq", FcElementMoreEq
},
386 { "contains", FcElementContains
},
387 { "not_contains", FcElementNotContains
},
388 { "plus", FcElementPlus
},
389 { "minus", FcElementMinus
},
390 { "times", FcElementTimes
},
391 { "divide", FcElementDivide
},
392 { "not", FcElementNot
},
393 { "if", FcElementIf
},
394 { "floor", FcElementFloor
},
395 { "ceil", FcElementCeil
},
396 { "round", FcElementRound
},
397 { "trunc", FcElementTrunc
},
399 #define NUM_ELEMENT_MAPS (int) (sizeof fcElementMap / sizeof fcElementMap[0])
402 FcElementMap (const XML_Char
*name
)
406 for (i
= 0; i
< NUM_ELEMENT_MAPS
; i
++)
407 if (!strcmp ((char *) name
, fcElementMap
[i
].name
))
408 return fcElementMap
[i
].element
;
409 return FcElementUnknown
;
412 typedef struct _FcPStack
{
413 struct _FcPStack
*prev
;
419 typedef enum _FcVStackTag
{
443 typedef struct _FcVStack
{
444 struct _FcVStack
*prev
;
445 FcPStack
*pstack
; /* related parse element */
465 typedef struct _FcConfigParse
{
472 int pstack_static_used
;
473 FcPStack pstack_static
[8];
474 int vstack_static_used
;
475 FcVStack vstack_static
[64];
478 typedef enum _FcConfigSeverity
{
479 FcSevereInfo
, FcSevereWarning
, FcSevereError
483 FcConfigMessage (FcConfigParse
*parse
, FcConfigSeverity severe
, const char *fmt
, ...)
485 const char *s
= "unknown";
488 va_start (args
, fmt
);
491 case FcSevereInfo
: s
= "info"; break;
492 case FcSevereWarning
: s
= "warning"; break;
493 case FcSevereError
: s
= "error"; break;
498 fprintf (stderr
, "Fontconfig %s: \"%s\", line %d: ", s
,
499 parse
->name
, (int)XML_GetCurrentLineNumber (parse
->parser
));
501 fprintf (stderr
, "Fontconfig %s: line %d: ", s
,
502 (int)XML_GetCurrentLineNumber (parse
->parser
));
503 if (severe
>= FcSevereError
)
504 parse
->error
= FcTrue
;
507 fprintf (stderr
, "Fontconfig %s: ", s
);
508 vfprintf (stderr
, fmt
, args
);
509 fprintf (stderr
, "\n");
515 FcTypeName (FcType type
)
541 FcTypecheckValue (FcConfigParse
*parse
, FcType value
, FcType type
)
543 if (value
== FcTypeInteger
)
544 value
= FcTypeDouble
;
545 if (type
== FcTypeInteger
)
549 if ((value
== FcTypeLangSet
&& type
== FcTypeString
) ||
550 (value
== FcTypeString
&& type
== FcTypeLangSet
))
552 if (type
== (FcType
) -1)
554 FcConfigMessage (parse
, FcSevereWarning
, "saw %s, expected %s",
555 FcTypeName (value
), FcTypeName (type
));
560 FcTypecheckExpr (FcConfigParse
*parse
, FcExpr
*expr
, FcType type
)
562 const FcObjectType
*o
;
565 /* If parsing the expression failed, some nodes may be NULL */
572 FcTypecheckValue (parse
, FcTypeDouble
, type
);
575 FcTypecheckValue (parse
, FcTypeString
, type
);
578 FcTypecheckValue (parse
, FcTypeMatrix
, type
);
581 FcTypecheckValue (parse
, FcTypeBool
, type
);
584 FcTypecheckValue (parse
, FcTypeCharSet
, type
);
589 o
= FcNameGetObjectType (FcObjectName (expr
->u
.object
));
591 FcTypecheckValue (parse
, o
->type
, type
);
594 c
= FcNameGetConstant (expr
->u
.constant
);
597 o
= FcNameGetObjectType (c
->object
);
599 FcTypecheckValue (parse
, o
->type
, type
);
602 FcConfigMessage (parse
, FcSevereWarning
,
603 "invalid constant used : %s",
607 FcTypecheckExpr (parse
, expr
->u
.tree
.left
, FcTypeBool
);
608 FcTypecheckExpr (parse
, expr
->u
.tree
.right
->u
.tree
.left
, type
);
609 FcTypecheckExpr (parse
, expr
->u
.tree
.right
->u
.tree
.right
, type
);
612 case FcOpAssignReplace
:
621 case FcOpNotContains
:
623 FcTypecheckValue (parse
, FcTypeBool
, type
);
632 FcTypecheckExpr (parse
, expr
->u
.tree
.left
, type
);
633 FcTypecheckExpr (parse
, expr
->u
.tree
.right
, type
);
636 FcTypecheckValue (parse
, FcTypeBool
, type
);
637 FcTypecheckExpr (parse
, expr
->u
.tree
.left
, FcTypeBool
);
643 FcTypecheckValue (parse
, FcTypeDouble
, type
);
644 FcTypecheckExpr (parse
, expr
->u
.tree
.left
, FcTypeDouble
);
652 FcTestCreate (FcConfigParse
*parse
,
655 const FcChar8
*field
,
659 FcTest
*test
= (FcTest
*) malloc (sizeof (FcTest
));
663 const FcObjectType
*o
;
665 FcMemAlloc (FC_MEM_TEST
, sizeof (FcTest
));
669 test
->object
= FcObjectFromName ((const char *) field
);
672 o
= FcNameGetObjectType (FcObjectName (test
->object
));
674 FcTypecheckExpr (parse
, expr
, o
->type
);
680 FcEditCreate (FcConfigParse
*parse
,
684 FcValueBinding binding
)
686 FcEdit
*e
= (FcEdit
*) malloc (sizeof (FcEdit
));
690 const FcObjectType
*o
;
696 e
->binding
= binding
;
697 o
= FcNameGetObjectType (FcObjectName (e
->object
));
699 FcTypecheckExpr (parse
, expr
, o
->type
);
705 FcVStackCreateAndPush (FcConfigParse
*parse
)
709 if (parse
->vstack_static_used
< sizeof (parse
->vstack_static
) / sizeof (parse
->vstack_static
[0]))
710 new = &parse
->vstack_static
[parse
->vstack_static_used
++];
713 new = malloc (sizeof (FcVStack
));
716 FcMemAlloc (FC_MEM_VSTACK
, sizeof (FcVStack
));
718 new->tag
= FcVStackNone
;
721 new->prev
= parse
->vstack
;
722 new->pstack
= parse
->pstack
? parse
->pstack
->prev
: 0;
729 FcVStackPushString (FcConfigParse
*parse
, FcVStackTag tag
, FcChar8
*string
)
731 FcVStack
*vstack
= FcVStackCreateAndPush (parse
);
734 vstack
->u
.string
= string
;
740 FcVStackPushInteger (FcConfigParse
*parse
, int integer
)
742 FcVStack
*vstack
= FcVStackCreateAndPush (parse
);
745 vstack
->u
.integer
= integer
;
746 vstack
->tag
= FcVStackInteger
;
751 FcVStackPushDouble (FcConfigParse
*parse
, double _double
)
753 FcVStack
*vstack
= FcVStackCreateAndPush (parse
);
756 vstack
->u
._double
= _double
;
757 vstack
->tag
= FcVStackDouble
;
762 FcVStackPushMatrix (FcConfigParse
*parse
, FcMatrix
*matrix
)
765 matrix
= FcMatrixCopy (matrix
);
768 vstack
= FcVStackCreateAndPush (parse
);
771 vstack
->u
.matrix
= matrix
;
772 vstack
->tag
= FcVStackMatrix
;
777 FcVStackPushBool (FcConfigParse
*parse
, FcBool bool_
)
779 FcVStack
*vstack
= FcVStackCreateAndPush (parse
);
782 vstack
->u
.bool_
= bool_
;
783 vstack
->tag
= FcVStackBool
;
788 FcVStackPushTest (FcConfigParse
*parse
, FcTest
*test
)
790 FcVStack
*vstack
= FcVStackCreateAndPush (parse
);
793 vstack
->u
.test
= test
;
794 vstack
->tag
= FcVStackTest
;
799 FcVStackPushExpr (FcConfigParse
*parse
, FcVStackTag tag
, FcExpr
*expr
)
801 FcVStack
*vstack
= FcVStackCreateAndPush (parse
);
804 vstack
->u
.expr
= expr
;
810 FcVStackPushEdit (FcConfigParse
*parse
, FcEdit
*edit
)
812 FcVStack
*vstack
= FcVStackCreateAndPush (parse
);
815 vstack
->u
.edit
= edit
;
816 vstack
->tag
= FcVStackEdit
;
821 FcVStackPushPattern (FcConfigParse
*parse
, FcPattern
*pattern
)
823 FcVStack
*vstack
= FcVStackCreateAndPush (parse
);
826 vstack
->u
.pattern
= pattern
;
827 vstack
->tag
= FcVStackPattern
;
832 FcVStackFetch (FcConfigParse
*parse
, int off
)
836 for (vstack
= parse
->vstack
; vstack
&& off
-- > 0; vstack
= vstack
->prev
);
841 FcVStackPeek (FcConfigParse
*parse
)
843 FcVStack
*vstack
= parse
->vstack
;
845 return vstack
&& vstack
->pstack
== parse
->pstack
? vstack
: 0;
849 FcVStackPopAndDestroy (FcConfigParse
*parse
)
851 FcVStack
*vstack
= parse
->vstack
;
853 if (!vstack
|| vstack
->pstack
!= parse
->pstack
)
856 parse
->vstack
= vstack
->prev
;
858 switch (vstack
->tag
) {
864 case FcVStackConstant
:
866 FcStrFree (vstack
->u
.string
);
868 case FcVStackPattern
:
869 FcPatternDestroy (vstack
->u
.pattern
);
871 case FcVStackInteger
:
875 FcMatrixFree (vstack
->u
.matrix
);
880 FcTestDestroy (vstack
->u
.test
);
885 case FcVStackDefault
:
886 FcExprDestroy (vstack
->u
.expr
);
889 FcEditDestroy (vstack
->u
.edit
);
893 if (vstack
== &parse
->vstack_static
[parse
->vstack_static_used
- 1])
894 parse
->vstack_static_used
--;
897 FcMemFree (FC_MEM_VSTACK
, sizeof (FcVStack
));
903 FcVStackClear (FcConfigParse
*parse
)
905 while (FcVStackPeek (parse
))
906 FcVStackPopAndDestroy (parse
);
910 FcVStackElements (FcConfigParse
*parse
)
913 FcVStack
*vstack
= parse
->vstack
;
914 while (vstack
&& vstack
->pstack
== parse
->pstack
)
917 vstack
= vstack
->prev
;
923 FcConfigSaveAttr (const XML_Char
**attr
)
933 for (i
= 0; attr
[i
]; i
++)
934 slen
+= strlen ((char *) attr
[i
]) + 1;
937 new = malloc ((i
+ 1) * sizeof (FcChar8
*) + slen
);
940 FcConfigMessage (0, FcSevereError
, "out of memory");
943 FcMemAlloc (FC_MEM_ATTR
, 1); /* size is too expensive */
944 s
= (FcChar8
*) (new + (i
+ 1));
945 for (i
= 0; attr
[i
]; i
++)
948 strcpy ((char *) s
, (char *) attr
[i
]);
949 s
+= strlen ((char *) s
) + 1;
956 FcPStackPush (FcConfigParse
*parse
, FcElement element
, const XML_Char
**attr
)
960 if (parse
->pstack_static_used
< sizeof (parse
->pstack_static
) / sizeof (parse
->pstack_static
[0]))
961 new = &parse
->pstack_static
[parse
->pstack_static_used
++];
964 new = malloc (sizeof (FcPStack
));
967 FcMemAlloc (FC_MEM_PSTACK
, sizeof (FcPStack
));
970 new->prev
= parse
->pstack
;
971 new->element
= element
;
972 new->attr
= FcConfigSaveAttr (attr
);
973 FcStrBufInit (&new->str
, 0, 0);
979 FcPStackPop (FcConfigParse
*parse
)
985 FcConfigMessage (parse
, FcSevereError
, "mismatching element");
988 FcVStackClear (parse
);
990 parse
->pstack
= old
->prev
;
991 FcStrBufDestroy (&old
->str
);
994 FcMemFree (FC_MEM_ATTR
, 1); /* size is to expensive */
998 if (old
== &parse
->pstack_static
[parse
->pstack_static_used
- 1])
999 parse
->pstack_static_used
--;
1002 FcMemFree (FC_MEM_PSTACK
, sizeof (FcPStack
));
1009 FcConfigInit (FcConfigParse
*parse
, const FcChar8
*name
, FcConfig
*config
, XML_Parser parser
)
1012 parse
->pstack_static_used
= 0;
1014 parse
->vstack_static_used
= 0;
1015 parse
->error
= FcFalse
;
1017 parse
->config
= config
;
1018 parse
->parser
= parser
;
1023 FcConfigCleanup (FcConfigParse
*parse
)
1025 while (parse
->pstack
)
1026 FcPStackPop (parse
);
1029 static const FcChar8
*
1030 FcConfigGetAttribute (FcConfigParse
*parse
, const char *attr
)
1036 attrs
= parse
->pstack
->attr
;
1042 if (!strcmp ((char *) *attrs
, attr
))
1050 FcStartElement(void *userData
, const XML_Char
*name
, const XML_Char
**attr
)
1052 FcConfigParse
*parse
= userData
;
1055 element
= FcElementMap (name
);
1056 if (element
== FcElementUnknown
)
1057 FcConfigMessage (parse
, FcSevereWarning
, "unknown element \"%s\"", name
);
1059 if (!FcPStackPush (parse
, element
, attr
))
1061 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1068 FcParseBlank (FcConfigParse
*parse
)
1070 int n
= FcVStackElements (parse
);
1073 FcVStack
*v
= FcVStackFetch (parse
, n
);
1074 if (v
->tag
!= FcVStackInteger
)
1075 FcConfigMessage (parse
, FcSevereError
, "non-integer blank");
1078 if (!parse
->config
->blanks
)
1080 parse
->config
->blanks
= FcBlanksCreate ();
1081 if (!parse
->config
->blanks
)
1083 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1087 if (!FcBlanksAdd (parse
->config
->blanks
, v
->u
.integer
))
1089 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1097 FcParseRescan (FcConfigParse
*parse
)
1099 int n
= FcVStackElements (parse
);
1102 FcVStack
*v
= FcVStackFetch (parse
, n
);
1103 if (v
->tag
!= FcVStackInteger
)
1104 FcConfigMessage (parse
, FcSevereWarning
, "non-integer rescan");
1106 parse
->config
->rescanInterval
= v
->u
.integer
;
1111 FcParseInt (FcConfigParse
*parse
)
1118 s
= FcStrBufDoneStatic (&parse
->pstack
->str
);
1121 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1125 l
= (int) strtol ((char *) s
, (char **)&end
, 0);
1126 if (end
!= s
+ strlen ((char *) s
))
1127 FcConfigMessage (parse
, FcSevereError
, "\"%s\": not a valid integer", s
);
1129 FcVStackPushInteger (parse
, l
);
1130 FcStrBufDestroy (&parse
->pstack
->str
);
1134 * idea copied from glib g_ascii_strtod with
1135 * permission of the author (Alexander Larsson)
1141 FcStrtod (char *s
, char **end
)
1143 struct lconv
*locale_data
;
1148 * Have to swap the decimal point to match the current locale
1149 * if that locale doesn't use 0x2e
1151 if ((dot
= strchr (s
, 0x2e)) &&
1152 (locale_data
= localeconv ()) &&
1153 (locale_data
->decimal_point
[0] != 0x2e ||
1154 locale_data
->decimal_point
[1] != 0))
1157 int slen
= strlen (s
);
1158 int dlen
= strlen (locale_data
->decimal_point
);
1160 if (slen
+ dlen
> (int) sizeof (buf
))
1170 strncpy (buf
, s
, dot
- s
);
1172 strcpy (buf
+ (dot
- s
), locale_data
->decimal_point
);
1173 /* rest of number */
1174 strcpy (buf
+ (dot
- s
) + dlen
, dot
+ 1);
1176 v
= strtod (buf
, &buf_end
);
1178 buf_end
= s
+ (buf_end
- buf
);
1180 buf_end
-= dlen
- 1;
1187 v
= strtod (s
, end
);
1192 FcParseDouble (FcConfigParse
*parse
)
1199 s
= FcStrBufDoneStatic (&parse
->pstack
->str
);
1202 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1206 d
= FcStrtod ((char *) s
, (char **)&end
);
1207 if (end
!= s
+ strlen ((char *) s
))
1208 FcConfigMessage (parse
, FcSevereError
, "\"%s\": not a valid double", s
);
1210 FcVStackPushDouble (parse
, d
);
1211 FcStrBufDestroy (&parse
->pstack
->str
);
1215 FcParseString (FcConfigParse
*parse
, FcVStackTag tag
)
1221 s
= FcStrBufDone (&parse
->pstack
->str
);
1224 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1227 if (!FcVStackPushString (parse
, tag
, s
))
1232 FcParseMatrix (FcConfigParse
*parse
)
1235 enum { m_done
, m_xx
, m_xy
, m_yx
, m_yy
} matrix_state
= m_yy
;
1238 while ((vstack
= FcVStackPeek (parse
)))
1241 switch (vstack
->tag
) {
1242 case FcVStackInteger
:
1243 v
= vstack
->u
.integer
;
1245 case FcVStackDouble
:
1246 v
= vstack
->u
._double
;
1249 FcConfigMessage (parse
, FcSevereError
, "non-double matrix element");
1253 switch (matrix_state
) {
1254 case m_xx
: m
.xx
= v
; break;
1255 case m_xy
: m
.xy
= v
; break;
1256 case m_yx
: m
.yx
= v
; break;
1257 case m_yy
: m
.yy
= v
; break;
1260 FcVStackPopAndDestroy (parse
);
1263 if (matrix_state
!= m_done
)
1264 FcConfigMessage (parse
, FcSevereError
, "wrong number of matrix elements");
1266 FcVStackPushMatrix (parse
, &m
);
1270 FcConfigLexBool (FcConfigParse
*parse
, const FcChar8
*bool_
)
1272 FcBool result
= FcFalse
;
1274 if (!FcNameBool (bool_
, &result
))
1275 FcConfigMessage (parse
, FcSevereWarning
, "\"%s\" is not known boolean",
1281 FcParseBool (FcConfigParse
*parse
)
1287 s
= FcStrBufDoneStatic (&parse
->pstack
->str
);
1290 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1293 FcVStackPushBool (parse
, FcConfigLexBool (parse
, s
));
1294 FcStrBufDestroy (&parse
->pstack
->str
);
1298 FcConfigLexBinding (FcConfigParse
*parse
,
1299 const FcChar8
*binding_string
,
1300 FcValueBinding
*binding_ret
)
1302 FcValueBinding binding
;
1304 if (!binding_string
)
1305 binding
= FcValueBindingWeak
;
1308 if (!strcmp ((char *) binding_string
, "weak"))
1309 binding
= FcValueBindingWeak
;
1310 else if (!strcmp ((char *) binding_string
, "strong"))
1311 binding
= FcValueBindingStrong
;
1312 else if (!strcmp ((char *) binding_string
, "same"))
1313 binding
= FcValueBindingSame
;
1316 FcConfigMessage (parse
, FcSevereWarning
, "invalid binding \"%s\"", binding_string
);
1320 *binding_ret
= binding
;
1325 FcParseFamilies (FcConfigParse
*parse
, FcVStackTag tag
)
1328 FcExpr
*left
, *expr
= 0, *new;
1330 while ((vstack
= FcVStackPeek (parse
)))
1332 if (vstack
->tag
!= FcVStackFamily
)
1334 FcConfigMessage (parse
, FcSevereWarning
, "non-family");
1335 FcVStackPopAndDestroy (parse
);
1338 left
= vstack
->u
.expr
;
1339 vstack
->tag
= FcVStackNone
;
1340 FcVStackPopAndDestroy (parse
);
1343 new = FcExprCreateOp (left
, FcOpComma
, expr
);
1346 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1347 FcExprDestroy (left
);
1348 FcExprDestroy (expr
);
1358 if (!FcVStackPushExpr (parse
, tag
, expr
))
1360 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1361 FcExprDestroy (expr
);
1367 FcParseFamily (FcConfigParse
*parse
)
1374 s
= FcStrBufDoneStatic (&parse
->pstack
->str
);
1377 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1380 expr
= FcExprCreateString (s
);
1381 FcStrBufDestroy (&parse
->pstack
->str
);
1383 FcVStackPushExpr (parse
, FcVStackFamily
, expr
);
1387 FcParseAlias (FcConfigParse
*parse
)
1389 FcExpr
*family
= 0, *accept
= 0, *prefer
= 0, *def
= 0, *new = 0;
1390 FcEdit
*edit
= 0, *next
;
1393 FcValueBinding binding
;
1395 if (!FcConfigLexBinding (parse
, FcConfigGetAttribute (parse
, "binding"), &binding
))
1397 while ((vstack
= FcVStackPeek (parse
)))
1399 switch (vstack
->tag
) {
1400 case FcVStackFamily
:
1403 new = FcExprCreateOp (vstack
->u
.expr
, FcOpComma
, family
);
1405 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1410 new = vstack
->u
.expr
;
1414 vstack
->tag
= FcVStackNone
;
1417 case FcVStackPrefer
:
1419 FcExprDestroy (prefer
);
1420 prefer
= vstack
->u
.expr
;
1421 vstack
->tag
= FcVStackNone
;
1423 case FcVStackAccept
:
1425 FcExprDestroy (accept
);
1426 accept
= vstack
->u
.expr
;
1427 vstack
->tag
= FcVStackNone
;
1429 case FcVStackDefault
:
1431 FcExprDestroy (def
);
1432 def
= vstack
->u
.expr
;
1433 vstack
->tag
= FcVStackNone
;
1436 FcConfigMessage (parse
, FcSevereWarning
, "bad alias");
1439 FcVStackPopAndDestroy (parse
);
1443 FcConfigMessage (parse
, FcSevereError
, "missing family in alias");
1445 FcExprDestroy (prefer
);
1447 FcExprDestroy (accept
);
1449 FcExprDestroy (def
);
1454 edit
= FcEditCreate (parse
,
1462 FcExprDestroy (prefer
);
1467 edit
= FcEditCreate (parse
,
1475 FcExprDestroy (accept
);
1480 edit
= FcEditCreate (parse
,
1488 FcExprDestroy (def
);
1492 test
= FcTestCreate (parse
, FcMatchPattern
,
1494 (FcChar8
*) FC_FAMILY
,
1498 if (!FcConfigAddEdit (parse
->config
, test
, edit
, FcMatchPattern
))
1499 FcTestDestroy (test
);
1502 FcExprDestroy (family
);
1506 FcPopExpr (FcConfigParse
*parse
)
1508 FcVStack
*vstack
= FcVStackPeek (parse
);
1512 switch (vstack
->tag
) {
1515 case FcVStackString
:
1516 case FcVStackFamily
:
1517 expr
= FcExprCreateString (vstack
->u
.string
);
1520 expr
= FcExprCreateField ((char *) vstack
->u
.string
);
1522 case FcVStackConstant
:
1523 expr
= FcExprCreateConst (vstack
->u
.string
);
1526 /* XXX: What's the correct action here? (CDW) */
1528 case FcVStackPrefer
:
1529 case FcVStackAccept
:
1530 case FcVStackDefault
:
1531 expr
= vstack
->u
.expr
;
1532 vstack
->tag
= FcVStackNone
;
1534 case FcVStackInteger
:
1535 expr
= FcExprCreateInteger (vstack
->u
.integer
);
1537 case FcVStackDouble
:
1538 expr
= FcExprCreateDouble (vstack
->u
._double
);
1540 case FcVStackMatrix
:
1541 expr
= FcExprCreateMatrix (vstack
->u
.matrix
);
1544 expr
= FcExprCreateBool (vstack
->u
.bool_
);
1549 expr
= vstack
->u
.expr
;
1550 vstack
->tag
= FcVStackNone
;
1557 FcVStackPopAndDestroy (parse
);
1562 * This builds a tree of binary operations. Note
1563 * that every operator is defined so that if only
1564 * a single operand is contained, the value of the
1565 * whole expression is the value of the operand.
1567 * This code reduces in that case to returning that
1571 FcPopBinary (FcConfigParse
*parse
, FcOp op
)
1573 FcExpr
*left
, *expr
= 0, *new;
1575 while ((left
= FcPopExpr (parse
)))
1579 new = FcExprCreateOp (left
, op
, expr
);
1582 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1583 FcExprDestroy (left
);
1584 FcExprDestroy (expr
);
1596 FcParseBinary (FcConfigParse
*parse
, FcOp op
)
1598 FcExpr
*expr
= FcPopBinary (parse
, op
);
1600 FcVStackPushExpr (parse
, FcVStackExpr
, expr
);
1604 * This builds a a unary operator, it consumes only
1609 FcPopUnary (FcConfigParse
*parse
, FcOp op
)
1611 FcExpr
*operand
, *new = 0;
1613 if ((operand
= FcPopExpr (parse
)))
1615 new = FcExprCreateOp (operand
, op
, 0);
1618 FcExprDestroy (operand
);
1619 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1626 FcParseUnary (FcConfigParse
*parse
, FcOp op
)
1628 FcExpr
*expr
= FcPopUnary (parse
, op
);
1630 FcVStackPushExpr (parse
, FcVStackExpr
, expr
);
1634 FcParseInclude (FcConfigParse
*parse
)
1638 FcBool ignore_missing
= FcFalse
;
1640 s
= FcStrBufDoneStatic (&parse
->pstack
->str
);
1643 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1646 i
= FcConfigGetAttribute (parse
, "ignore_missing");
1647 if (i
&& FcConfigLexBool (parse
, (FcChar8
*) i
) == FcTrue
)
1648 ignore_missing
= FcTrue
;
1649 if (!FcConfigParseAndLoad (parse
->config
, s
, !ignore_missing
))
1650 parse
->error
= FcTrue
;
1651 FcStrBufDestroy (&parse
->pstack
->str
);
1654 typedef struct _FcOpMap
{
1660 FcConfigLexOp (const FcChar8
*op
, const FcOpMap
*map
, int nmap
)
1664 for (i
= 0; i
< nmap
; i
++)
1665 if (!strcmp ((char *) op
, map
[i
].name
))
1670 static const FcOpMap fcCompareOps
[] = {
1671 { "eq", FcOpEqual
},
1672 { "not_eq", FcOpNotEqual
},
1673 { "less", FcOpLess
},
1674 { "less_eq", FcOpLessEqual
},
1675 { "more", FcOpMore
},
1676 { "more_eq", FcOpMoreEqual
},
1677 { "contains", FcOpContains
},
1678 { "not_contains", FcOpNotContains
}
1681 #define NUM_COMPARE_OPS (int) (sizeof fcCompareOps / sizeof fcCompareOps[0])
1684 FcConfigLexCompare (const FcChar8
*compare
)
1686 return FcConfigLexOp (compare
, fcCompareOps
, NUM_COMPARE_OPS
);
1690 FcParseTest (FcConfigParse
*parse
)
1692 const FcChar8
*kind_string
;
1694 const FcChar8
*qual_string
;
1696 const FcChar8
*name
;
1697 const FcChar8
*compare_string
;
1702 kind_string
= FcConfigGetAttribute (parse
, "target");
1704 kind
= FcMatchDefault
;
1707 if (!strcmp ((char *) kind_string
, "pattern"))
1708 kind
= FcMatchPattern
;
1709 else if (!strcmp ((char *) kind_string
, "font"))
1711 else if (!strcmp ((char *) kind_string
, "scan"))
1713 else if (!strcmp ((char *) kind_string
, "default"))
1714 kind
= FcMatchDefault
;
1717 FcConfigMessage (parse
, FcSevereWarning
, "invalid test target \"%s\"", kind_string
);
1721 qual_string
= FcConfigGetAttribute (parse
, "qual");
1726 if (!strcmp ((char *) qual_string
, "any"))
1728 else if (!strcmp ((char *) qual_string
, "all"))
1730 else if (!strcmp ((char *) qual_string
, "first"))
1732 else if (!strcmp ((char *) qual_string
, "not_first"))
1733 qual
= FcQualNotFirst
;
1736 FcConfigMessage (parse
, FcSevereWarning
, "invalid test qual \"%s\"", qual_string
);
1740 name
= FcConfigGetAttribute (parse
, "name");
1743 FcConfigMessage (parse
, FcSevereWarning
, "missing test name");
1746 compare_string
= FcConfigGetAttribute (parse
, "compare");
1747 if (!compare_string
)
1748 compare
= FcOpEqual
;
1751 compare
= FcConfigLexCompare (compare_string
);
1752 if (compare
== FcOpInvalid
)
1754 FcConfigMessage (parse
, FcSevereWarning
, "invalid test compare \"%s\"", compare_string
);
1758 expr
= FcPopBinary (parse
, FcOpComma
);
1761 FcConfigMessage (parse
, FcSevereWarning
, "missing test expression");
1764 test
= FcTestCreate (parse
, kind
, qual
, name
, compare
, expr
);
1767 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1770 FcVStackPushTest (parse
, test
);
1773 static const FcOpMap fcModeOps
[] = {
1774 { "assign", FcOpAssign
},
1775 { "assign_replace", FcOpAssignReplace
},
1776 { "prepend", FcOpPrepend
},
1777 { "prepend_first", FcOpPrependFirst
},
1778 { "append", FcOpAppend
},
1779 { "append_last", FcOpAppendLast
},
1782 #define NUM_MODE_OPS (int) (sizeof fcModeOps / sizeof fcModeOps[0])
1785 FcConfigLexMode (const FcChar8
*mode
)
1787 return FcConfigLexOp (mode
, fcModeOps
, NUM_MODE_OPS
);
1791 FcParseEdit (FcConfigParse
*parse
)
1793 const FcChar8
*name
;
1794 const FcChar8
*mode_string
;
1796 FcValueBinding binding
;
1800 name
= FcConfigGetAttribute (parse
, "name");
1803 FcConfigMessage (parse
, FcSevereWarning
, "missing edit name");
1806 mode_string
= FcConfigGetAttribute (parse
, "mode");
1811 mode
= FcConfigLexMode (mode_string
);
1812 if (mode
== FcOpInvalid
)
1814 FcConfigMessage (parse
, FcSevereWarning
, "invalid edit mode \"%s\"", mode_string
);
1818 if (!FcConfigLexBinding (parse
, FcConfigGetAttribute (parse
, "binding"), &binding
))
1821 expr
= FcPopBinary (parse
, FcOpComma
);
1822 edit
= FcEditCreate (parse
, FcObjectFromName ((char *) name
),
1823 mode
, expr
, binding
);
1826 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1827 FcExprDestroy (expr
);
1830 if (!FcVStackPushEdit (parse
, edit
))
1831 FcEditDestroy (edit
);
1835 FcParseMatch (FcConfigParse
*parse
)
1837 const FcChar8
*kind_name
;
1843 kind_name
= FcConfigGetAttribute (parse
, "target");
1845 kind
= FcMatchPattern
;
1848 if (!strcmp ((char *) kind_name
, "pattern"))
1849 kind
= FcMatchPattern
;
1850 else if (!strcmp ((char *) kind_name
, "font"))
1852 else if (!strcmp ((char *) kind_name
, "scan"))
1856 FcConfigMessage (parse
, FcSevereWarning
, "invalid match target \"%s\"", kind_name
);
1860 while ((vstack
= FcVStackPeek (parse
)))
1862 switch (vstack
->tag
) {
1864 vstack
->u
.test
->next
= test
;
1865 test
= vstack
->u
.test
;
1866 vstack
->tag
= FcVStackNone
;
1869 vstack
->u
.edit
->next
= edit
;
1870 edit
= vstack
->u
.edit
;
1871 vstack
->tag
= FcVStackNone
;
1872 if (kind
== FcMatchScan
&& edit
->object
> FC_MAX_BASE_OBJECT
)
1874 FcConfigMessage (parse
, FcSevereError
,
1875 "<match target=\"scan\"> cannot edit user-defined object \"%s\"",
1876 FcObjectName(edit
->object
));
1880 FcConfigMessage (parse
, FcSevereWarning
, "invalid match element");
1883 FcVStackPopAndDestroy (parse
);
1885 if (!FcConfigAddEdit (parse
->config
, test
, edit
, kind
))
1886 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1890 FcParseAcceptRejectFont (FcConfigParse
*parse
, FcElement element
)
1894 while ((vstack
= FcVStackPeek (parse
)))
1896 switch (vstack
->tag
) {
1898 if (!FcConfigGlobAdd (parse
->config
,
1900 element
== FcElementAcceptfont
))
1902 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1905 case FcVStackPattern
:
1906 if (!FcConfigPatternsAdd (parse
->config
,
1908 element
== FcElementAcceptfont
))
1910 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1913 vstack
->tag
= FcVStackNone
;
1916 FcConfigMessage (parse
, FcSevereWarning
, "bad font selector");
1919 FcVStackPopAndDestroy (parse
);
1925 FcPopValue (FcConfigParse
*parse
)
1927 FcVStack
*vstack
= FcVStackPeek (parse
);
1930 value
.type
= FcTypeVoid
;
1935 switch (vstack
->tag
) {
1936 case FcVStackString
:
1937 value
.u
.s
= FcStrCopy (vstack
->u
.string
);
1939 value
.type
= FcTypeString
;
1941 case FcVStackConstant
:
1942 if (FcNameConstant (vstack
->u
.string
, &value
.u
.i
))
1943 value
.type
= FcTypeInteger
;
1945 case FcVStackInteger
:
1946 value
.u
.i
= vstack
->u
.integer
;
1947 value
.type
= FcTypeInteger
;
1949 case FcVStackDouble
:
1950 value
.u
.d
= vstack
->u
._double
;
1951 value
.type
= FcTypeInteger
;
1953 case FcVStackMatrix
:
1954 value
.u
.m
= FcMatrixCopy (vstack
->u
.matrix
);
1956 value
.type
= FcTypeMatrix
;
1959 value
.u
.b
= vstack
->u
.bool_
;
1960 value
.type
= FcTypeBool
;
1963 FcConfigMessage (parse
, FcSevereWarning
, "unknown pattern element %d",
1967 FcVStackPopAndDestroy (parse
);
1973 FcParsePatelt (FcConfigParse
*parse
)
1976 FcPattern
*pattern
= FcPatternCreate ();
1981 FcConfigMessage (parse
, FcSevereError
, "out of memory");
1985 name
= (char *) FcConfigGetAttribute (parse
, "name");
1988 FcConfigMessage (parse
, FcSevereWarning
, "missing pattern element name");
1989 FcPatternDestroy (pattern
);
1995 value
= FcPopValue (parse
);
1996 if (value
.type
== FcTypeVoid
)
1998 if (!FcPatternAdd (pattern
, name
, value
, FcTrue
))
2000 FcConfigMessage (parse
, FcSevereError
, "out of memory");
2001 FcValueDestroy(value
);
2004 FcValueDestroy(value
);
2007 FcVStackPushPattern (parse
, pattern
);
2011 FcParsePattern (FcConfigParse
*parse
)
2014 FcPattern
*pattern
= FcPatternCreate ();
2018 FcConfigMessage (parse
, FcSevereError
, "out of memory");
2022 while ((vstack
= FcVStackPeek (parse
)))
2024 switch (vstack
->tag
) {
2025 case FcVStackPattern
:
2026 if (!FcPatternAppend (pattern
, vstack
->u
.pattern
))
2028 FcConfigMessage (parse
, FcSevereError
, "out of memory");
2029 FcPatternDestroy (pattern
);
2034 FcConfigMessage (parse
, FcSevereWarning
, "unknown pattern element");
2037 FcVStackPopAndDestroy (parse
);
2040 FcVStackPushPattern (parse
, pattern
);
2044 FcEndElement(void *userData
, const XML_Char
*name
)
2046 FcConfigParse
*parse
= userData
;
2051 switch (parse
->pstack
->element
) {
2054 case FcElementFontconfig
:
2057 data
= FcStrBufDoneStatic (&parse
->pstack
->str
);
2060 FcConfigMessage (parse
, FcSevereError
, "out of memory");
2064 if (strcmp (data
, "CUSTOMFONTDIR") == 0)
2068 data
= malloc (1000);
2071 FcConfigMessage (parse
, FcSevereError
, "out of memory");
2074 FcMemAlloc (FC_MEM_STRING
, 1000);
2075 if(!GetModuleFileName(NULL
, data
, 1000))
2077 FcConfigMessage (parse
, FcSevereError
, "GetModuleFileName failed");
2081 p
= strrchr (data
, '\\');
2083 strcat (data
, "\\fonts");
2085 else if (strcmp (data
, "APPSHAREFONTDIR") == 0)
2089 data
= malloc (1000);
2092 FcConfigMessage (parse
, FcSevereError
, "out of memory");
2095 FcMemAlloc (FC_MEM_STRING
, 1000);
2096 if(!GetModuleFileName(NULL
, data
, 1000))
2098 FcConfigMessage (parse
, FcSevereError
, "GetModuleFileName failed");
2102 p
= strrchr (data
, '\\');
2104 strcat (data
, "\\..\\share\\fonts");
2106 else if (strcmp (data
, "WINDOWSFONTDIR") == 0)
2110 data
= malloc (1000);
2113 FcConfigMessage (parse
, FcSevereError
, "out of memory");
2116 FcMemAlloc (FC_MEM_STRING
, 1000);
2117 rc
= GetWindowsDirectory (data
, 800);
2118 if (rc
== 0 || rc
> 800)
2120 FcConfigMessage (parse
, FcSevereError
, "GetWindowsDirectory failed");
2124 if (data
[strlen (data
) - 1] != '\\')
2125 strcat (data
, "\\");
2126 strcat (data
, "fonts");
2129 if (strlen ((char *) data
) == 0)
2130 FcConfigMessage (parse
, FcSevereWarning
, "empty font directory name ignored");
2131 else if (!FcStrUsesHome (data
) || FcConfigHome ())
2133 if (!FcConfigAddDir (parse
->config
, data
))
2134 FcConfigMessage (parse
, FcSevereError
, "out of memory; cannot add directory %s", data
);
2136 FcStrBufDestroy (&parse
->pstack
->str
);
2138 case FcElementCacheDir
:
2139 data
= FcStrBufDone (&parse
->pstack
->str
);
2142 FcConfigMessage (parse
, FcSevereError
, "out of memory");
2146 if (strcmp (data
, "WINDOWSTEMPDIR_FONTCONFIG_CACHE") == 0)
2150 data
= malloc (1000);
2153 FcConfigMessage (parse
, FcSevereError
, "out of memory");
2156 FcMemAlloc (FC_MEM_STRING
, 1000);
2157 rc
= GetTempPath (800, data
);
2158 if (rc
== 0 || rc
> 800)
2160 FcConfigMessage (parse
, FcSevereError
, "GetWindowsDirectory failed");
2164 if (data
[strlen (data
) - 1] != '\\')
2165 strcat (data
, "\\");
2166 strcat (data
, "fontconfig\\cache");
2169 if (!FcStrUsesHome (data
) || FcConfigHome ())
2171 if (!FcConfigAddCacheDir (parse
->config
, data
))
2172 FcConfigMessage (parse
, FcSevereError
, "out of memory; cannot add cache directory %s", data
);
2177 case FcElementCache
:
2178 data
= FcStrBufDoneStatic (&parse
->pstack
->str
);
2181 FcConfigMessage (parse
, FcSevereError
, "out of memory");
2184 /* discard this data; no longer used */
2185 FcStrBufDestroy (&parse
->pstack
->str
);
2187 case FcElementInclude
:
2188 FcParseInclude (parse
);
2190 case FcElementConfig
:
2192 case FcElementMatch
:
2193 FcParseMatch (parse
);
2195 case FcElementAlias
:
2196 FcParseAlias (parse
);
2199 case FcElementBlank
:
2200 FcParseBlank (parse
);
2202 case FcElementRescan
:
2203 FcParseRescan (parse
);
2206 case FcElementPrefer
:
2207 FcParseFamilies (parse
, FcVStackPrefer
);
2209 case FcElementAccept
:
2210 FcParseFamilies (parse
, FcVStackAccept
);
2212 case FcElementDefault
:
2213 FcParseFamilies (parse
, FcVStackDefault
);
2215 case FcElementFamily
:
2216 FcParseFamily (parse
);
2220 FcParseTest (parse
);
2223 FcParseEdit (parse
);
2229 case FcElementDouble
:
2230 FcParseDouble (parse
);
2232 case FcElementString
:
2233 FcParseString (parse
, FcVStackString
);
2235 case FcElementMatrix
:
2236 FcParseMatrix (parse
);
2239 FcParseBool (parse
);
2241 case FcElementCharset
:
2242 /* FcParseCharset (parse); */
2244 case FcElementSelectfont
:
2246 case FcElementAcceptfont
:
2247 case FcElementRejectfont
:
2248 FcParseAcceptRejectFont (parse
, parse
->pstack
->element
);
2251 FcParseString (parse
, FcVStackGlob
);
2253 case FcElementPattern
:
2254 FcParsePattern (parse
);
2256 case FcElementPatelt
:
2257 FcParsePatelt (parse
);
2260 FcParseString (parse
, FcVStackField
);
2262 case FcElementConst
:
2263 FcParseString (parse
, FcVStackConstant
);
2266 FcParseBinary (parse
, FcOpOr
);
2269 FcParseBinary (parse
, FcOpAnd
);
2272 FcParseBinary (parse
, FcOpEqual
);
2274 case FcElementNotEq
:
2275 FcParseBinary (parse
, FcOpNotEqual
);
2278 FcParseBinary (parse
, FcOpLess
);
2280 case FcElementLessEq
:
2281 FcParseBinary (parse
, FcOpLessEqual
);
2284 FcParseBinary (parse
, FcOpMore
);
2286 case FcElementMoreEq
:
2287 FcParseBinary (parse
, FcOpMoreEqual
);
2289 case FcElementContains
:
2290 FcParseBinary (parse
, FcOpContains
);
2292 case FcElementNotContains
:
2293 FcParseBinary (parse
, FcOpNotContains
);
2296 FcParseBinary (parse
, FcOpPlus
);
2298 case FcElementMinus
:
2299 FcParseBinary (parse
, FcOpMinus
);
2301 case FcElementTimes
:
2302 FcParseBinary (parse
, FcOpTimes
);
2304 case FcElementDivide
:
2305 FcParseBinary (parse
, FcOpDivide
);
2308 FcParseUnary (parse
, FcOpNot
);
2311 FcParseBinary (parse
, FcOpQuest
);
2313 case FcElementFloor
:
2314 FcParseUnary (parse
, FcOpFloor
);
2317 FcParseUnary (parse
, FcOpCeil
);
2319 case FcElementRound
:
2320 FcParseUnary (parse
, FcOpRound
);
2322 case FcElementTrunc
:
2323 FcParseUnary (parse
, FcOpTrunc
);
2325 case FcElementUnknown
:
2328 (void) FcPStackPop (parse
);
2332 FcCharacterData (void *userData
, const XML_Char
*s
, int len
)
2334 FcConfigParse
*parse
= userData
;
2338 if (!FcStrBufData (&parse
->pstack
->str
, (FcChar8
*) s
, len
))
2339 FcConfigMessage (parse
, FcSevereError
, "out of memory");
2343 FcStartDoctypeDecl (void *userData
,
2344 const XML_Char
*doctypeName
,
2345 const XML_Char
*sysid
,
2346 const XML_Char
*pubid
,
2347 int has_internal_subset
)
2349 FcConfigParse
*parse
= userData
;
2351 if (strcmp ((char *) doctypeName
, "fontconfig") != 0)
2352 FcConfigMessage (parse
, FcSevereError
, "invalid doctype \"%s\"", doctypeName
);
2355 #ifdef ENABLE_LIBXML2
2358 FcInternalSubsetDecl (void *userData
,
2359 const XML_Char
*doctypeName
,
2360 const XML_Char
*sysid
,
2361 const XML_Char
*pubid
)
2363 FcStartDoctypeDecl (userData
, doctypeName
, sysid
, pubid
, 1);
2367 FcExternalSubsetDecl (void *userData
,
2368 const XML_Char
*doctypeName
,
2369 const XML_Char
*sysid
,
2370 const XML_Char
*pubid
)
2372 FcStartDoctypeDecl (userData
, doctypeName
, sysid
, pubid
, 0);
2375 #else /* ENABLE_LIBXML2 */
2378 FcEndDoctypeDecl (void *userData
)
2382 #endif /* ENABLE_LIBXML2 */
2385 FcSortCmpStr (const void *a
, const void *b
)
2387 const FcChar8
*as
= *((FcChar8
**) a
);
2388 const FcChar8
*bs
= *((FcChar8
**) b
);
2389 return FcStrCmp (as
, bs
);
2393 FcConfigParseAndLoadDir (FcConfig
*config
,
2394 const FcChar8
*name
,
2400 FcBool ret
= FcTrue
;
2405 d
= opendir ((char *) dir
);
2409 FcConfigMessage (0, FcSevereError
, "Cannot open config dir \"%s\"",
2415 file
= (FcChar8
*) malloc (strlen ((char *) dir
) + 1 + FC_MAX_FILE_LEN
+ 1);
2422 strcpy ((char *) file
, (char *) dir
);
2423 strcat ((char *) file
, "/");
2424 base
= file
+ strlen ((char *) file
);
2426 files
= FcStrSetCreate ();
2433 if (FcDebug () & FC_DBG_CONFIG
)
2434 printf ("\tScanning config dir %s\n", dir
);
2436 while (ret
&& (e
= readdir (d
)))
2439 #define TAIL ".conf"
2442 * Add all files of the form [0-9]*.conf
2444 if ('0' <= e
->d_name
[0] && e
->d_name
[0] <= '9' &&
2445 (d_len
= strlen (e
->d_name
)) < FC_MAX_FILE_LEN
&&
2447 strcmp (e
->d_name
+ d_len
- TAIL_LEN
, TAIL
) == 0)
2449 strcpy ((char *) base
, (char *) e
->d_name
);
2450 if (!FcStrSetAdd (files
, file
))
2460 qsort (files
->strs
, files
->num
, sizeof (FcChar8
*),
2461 (int (*)(const void *, const void *)) FcSortCmpStr
);
2462 for (i
= 0; ret
&& i
< files
->num
; i
++)
2463 ret
= FcConfigParseAndLoad (config
, files
->strs
[i
], complain
);
2466 FcStrSetDestroy (files
);
2472 return ret
|| !complain
;
2476 FcConfigParseAndLoad (FcConfig
*config
,
2477 const FcChar8
*name
,
2485 FcConfigParse parse
;
2486 FcBool error
= FcTrue
;
2488 #ifdef ENABLE_LIBXML2
2495 filename
= FcConfigFilename (name
);
2499 if (FcStrSetMember (config
->configFiles
, filename
))
2501 FcStrFree (filename
);
2505 if (!FcStrSetAdd (config
->configFiles
, filename
))
2507 FcStrFree (filename
);
2511 if (FcFileIsDir (filename
))
2513 FcBool ret
= FcConfigParseAndLoadDir (config
, name
, filename
, complain
);
2514 FcStrFree (filename
);
2518 if (FcDebug () & FC_DBG_CONFIG
)
2519 printf ("\tLoading config file %s\n", filename
);
2521 fd
= open ((char *) filename
, O_RDONLY
);
2523 FcStrFree (filename
);
2527 #ifdef ENABLE_LIBXML2
2528 memset(&sax
, 0, sizeof(sax
));
2530 sax
.internalSubset
= FcInternalSubsetDecl
;
2531 sax
.externalSubset
= FcExternalSubsetDecl
;
2532 sax
.startElement
= FcStartElement
;
2533 sax
.endElement
= FcEndElement
;
2534 sax
.characters
= FcCharacterData
;
2536 p
= xmlCreatePushParserCtxt (&sax
, &parse
, NULL
, 0, (const char *) filename
);
2538 p
= XML_ParserCreate ("UTF-8");
2540 FcStrFree (filename
);
2545 if (!FcConfigInit (&parse
, name
, config
, p
))
2548 #ifndef ENABLE_LIBXML2
2550 XML_SetUserData (p
, &parse
);
2552 XML_SetDoctypeDeclHandler (p
, FcStartDoctypeDecl
, FcEndDoctypeDecl
);
2553 XML_SetElementHandler (p
, FcStartElement
, FcEndElement
);
2554 XML_SetCharacterDataHandler (p
, FcCharacterData
);
2556 #endif /* ENABLE_LIBXML2 */
2559 #ifndef ENABLE_LIBXML2
2560 buf
= XML_GetBuffer (p
, BUFSIZ
);
2563 FcConfigMessage (&parse
, FcSevereError
, "cannot get parse buffer");
2567 len
= read (fd
, buf
, BUFSIZ
);
2570 FcConfigMessage (&parse
, FcSevereError
, "failed reading config file");
2574 #ifdef ENABLE_LIBXML2
2575 if (xmlParseChunk (p
, buf
, len
, len
== 0))
2577 if (!XML_ParseBuffer (p
, len
, len
== 0))
2580 FcConfigMessage (&parse
, FcSevereError
, "%s",
2581 XML_ErrorString (XML_GetErrorCode (p
)));
2585 error
= parse
.error
;
2587 FcConfigCleanup (&parse
);
2594 if (error
&& complain
)
2597 FcConfigMessage (0, FcSevereError
, "Cannot load config file \"%s\"", name
);
2599 FcConfigMessage (0, FcSevereError
, "Cannot load default config file");
2605 #include "fcaliastail.h"