]> git.wh0rd.org - fontconfig.git/blob - src/fcxml.c
Fix compiler warning
[fontconfig.git] / src / fcxml.c
1 /*
2 * $XFree86: xc/lib/fontconfig/src/fcxml.c,v 1.10 2002/06/08 17:32:05 keithp Exp $
3 *
4 * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
5 *
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.
15 *
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.
23 */
24
25 #include <stdarg.h>
26 #include "fcint.h"
27
28 #ifndef HAVE_EXPAT
29 #define HAVE_EXPAT 1
30 #endif
31
32 #ifndef HAVE_XML2
33 #define HAVE_XML2 0
34 #endif
35
36 #if HAVE_EXPAT
37 #ifndef HAVE_XMLPARSE_H
38 #define HAVE_XMLPARSE_H 0
39 #endif
40 #if HAVE_XMLPARSE_H
41 #include <xmlparse.h>
42 #else
43 #include <expat.h>
44 #endif
45 #endif
46
47 #if HAVE_XML2
48 #include "fclibxml2.h"
49 #endif
50
51 FcTest *
52 FcTestCreate (FcQual qual, const FcChar8 *field, FcOp compare, FcExpr *expr)
53 {
54 FcTest *test = (FcTest *) malloc (sizeof (FcTest));
55
56 if (test)
57 {
58 test->next = 0;
59 test->qual = qual;
60 test->field = (char *) FcStrCopy (field);
61 test->op = compare;
62 test->expr = expr;
63 }
64 return test;
65 }
66
67 void
68 FcTestDestroy (FcTest *test)
69 {
70 if (test->next)
71 FcTestDestroy (test->next);
72 FcExprDestroy (test->expr);
73 FcStrFree ((FcChar8 *) test->field);
74 free (test);
75 }
76
77 FcExpr *
78 FcExprCreateInteger (int i)
79 {
80 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
81
82 if (e)
83 {
84 e->op = FcOpInteger;
85 e->u.ival = i;
86 }
87 return e;
88 }
89
90 FcExpr *
91 FcExprCreateDouble (double d)
92 {
93 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
94
95 if (e)
96 {
97 e->op = FcOpDouble;
98 e->u.dval = d;
99 }
100 return e;
101 }
102
103 FcExpr *
104 FcExprCreateString (const FcChar8 *s)
105 {
106 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
107
108 if (e)
109 {
110 e->op = FcOpString;
111 e->u.sval = FcStrCopy (s);
112 }
113 return e;
114 }
115
116 FcExpr *
117 FcExprCreateMatrix (const FcMatrix *m)
118 {
119 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
120
121 if (e)
122 {
123 e->op = FcOpMatrix;
124 e->u.mval = FcMatrixCopy (m);
125 }
126 return e;
127 }
128
129 FcExpr *
130 FcExprCreateBool (FcBool b)
131 {
132 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
133
134 if (e)
135 {
136 e->op = FcOpBool;
137 e->u.bval = b;
138 }
139 return e;
140 }
141
142 FcExpr *
143 FcExprCreateNil (void)
144 {
145 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
146
147 if (e)
148 {
149 e->op = FcOpNil;
150 }
151 return e;
152 }
153
154 FcExpr *
155 FcExprCreateField (const char *field)
156 {
157 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
158
159 if (e)
160 {
161 e->op = FcOpField;
162 e->u.field = (char *) FcStrCopy ((FcChar8 *) field);
163 }
164 return e;
165 }
166
167 FcExpr *
168 FcExprCreateConst (const FcChar8 *constant)
169 {
170 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
171
172 if (e)
173 {
174 e->op = FcOpConst;
175 e->u.constant = FcStrCopy (constant);
176 }
177 return e;
178 }
179
180 FcExpr *
181 FcExprCreateOp (FcExpr *left, FcOp op, FcExpr *right)
182 {
183 FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
184
185 if (e)
186 {
187 e->op = op;
188 e->u.tree.left = left;
189 e->u.tree.right = right;
190 }
191 return e;
192 }
193
194 void
195 FcExprDestroy (FcExpr *e)
196 {
197 switch (e->op) {
198 case FcOpInteger:
199 break;
200 case FcOpDouble:
201 break;
202 case FcOpString:
203 FcStrFree (e->u.sval);
204 break;
205 case FcOpMatrix:
206 FcMatrixFree (e->u.mval);
207 break;
208 case FcOpCharSet:
209 FcCharSetDestroy (e->u.cval);
210 break;
211 case FcOpBool:
212 break;
213 case FcOpField:
214 FcStrFree ((FcChar8 *) e->u.field);
215 break;
216 case FcOpConst:
217 FcStrFree (e->u.constant);
218 break;
219 case FcOpAssign:
220 case FcOpAssignReplace:
221 case FcOpPrepend:
222 case FcOpPrependFirst:
223 case FcOpAppend:
224 case FcOpAppendLast:
225 break;
226 case FcOpOr:
227 case FcOpAnd:
228 case FcOpEqual:
229 case FcOpContains:
230 case FcOpNotEqual:
231 case FcOpLess:
232 case FcOpLessEqual:
233 case FcOpMore:
234 case FcOpMoreEqual:
235 case FcOpPlus:
236 case FcOpMinus:
237 case FcOpTimes:
238 case FcOpDivide:
239 case FcOpQuest:
240 case FcOpComma:
241 FcExprDestroy (e->u.tree.right);
242 /* fall through */
243 case FcOpNot:
244 FcExprDestroy (e->u.tree.left);
245 break;
246 case FcOpNil:
247 case FcOpInvalid:
248 break;
249 }
250 free (e);
251 }
252
253 FcEdit *
254 FcEditCreate (const char *field, FcOp op, FcExpr *expr)
255 {
256 FcEdit *e = (FcEdit *) malloc (sizeof (FcEdit));
257
258 if (e)
259 {
260 e->next = 0;
261 e->field = field; /* already saved in grammar */
262 e->op = op;
263 e->expr = expr;
264 }
265 return e;
266 }
267
268 void
269 FcEditDestroy (FcEdit *e)
270 {
271 if (e->next)
272 FcEditDestroy (e->next);
273 FcStrFree ((FcChar8 *) e->field);
274 if (e->expr)
275 FcExprDestroy (e->expr);
276 }
277
278 char *
279 FcConfigSaveField (const char *field)
280 {
281 return (char *) FcStrCopy ((FcChar8 *) field);
282 }
283
284 typedef enum _FcElement {
285 FcElementNone,
286 FcElementFontconfig,
287 FcElementDir,
288 FcElementCache,
289 FcElementInclude,
290 FcElementConfig,
291 FcElementMatch,
292 FcElementAlias,
293
294 FcElementBlank,
295 FcElementRescan,
296
297 FcElementPrefer,
298 FcElementAccept,
299 FcElementDefault,
300 FcElementFamily,
301
302 FcElementTest,
303 FcElementEdit,
304 FcElementInt,
305 FcElementDouble,
306 FcElementString,
307 FcElementMatrix,
308 FcElementBool,
309 FcElementCharset,
310 FcElementName,
311 FcElementConst,
312 FcElementOr,
313 FcElementAnd,
314 FcElementEq,
315 FcElementNotEq,
316 FcElementLess,
317 FcElementLessEq,
318 FcElementMore,
319 FcElementMoreEq,
320 FcElementPlus,
321 FcElementMinus,
322 FcElementTimes,
323 FcElementDivide,
324 FcElementNot,
325 FcElementIf,
326 FcElementUnknown
327 } FcElement;
328
329 static FcElement
330 FcElementMap (const XML_Char *name)
331 {
332 static struct {
333 char *name;
334 FcElement element;
335 } fcElementMap[] = {
336 { "fontconfig", FcElementFontconfig },
337 { "dir", FcElementDir },
338 { "cache", FcElementCache },
339 { "include", FcElementInclude },
340 { "config", FcElementConfig },
341 { "match", FcElementMatch },
342 { "alias", FcElementAlias },
343
344 { "blank", FcElementBlank },
345 { "rescan", FcElementRescan },
346
347 { "prefer", FcElementPrefer },
348 { "accept", FcElementAccept },
349 { "default", FcElementDefault },
350 { "family", FcElementFamily },
351
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 },
376
377 { 0, 0 }
378 };
379
380 int i;
381 for (i = 0; fcElementMap[i].name; i++)
382 if (!strcmp ((char *) name, fcElementMap[i].name))
383 return fcElementMap[i].element;
384 return FcElementUnknown;
385 }
386
387 typedef struct _FcPStack {
388 struct _FcPStack *prev;
389 FcElement element;
390 FcChar8 **attr;
391 FcStrBuf str;
392 } FcPStack;
393
394 typedef enum _FcVStackTag {
395 FcVStackNone,
396
397 FcVStackString,
398 FcVStackFamily,
399 FcVStackField,
400 FcVStackConstant,
401
402 FcVStackPrefer,
403 FcVStackAccept,
404 FcVStackDefault,
405
406 FcVStackInteger,
407 FcVStackDouble,
408 FcVStackMatrix,
409 FcVStackBool,
410
411 FcVStackTest,
412 FcVStackExpr,
413 FcVStackEdit
414 } FcVStackTag;
415
416 typedef struct _FcVStack {
417 struct _FcVStack *prev;
418 FcPStack *pstack; /* related parse element */
419 FcVStackTag tag;
420 union {
421 FcChar8 *string;
422
423 int integer;
424 double _double;
425 FcMatrix *matrix;
426 FcBool bool;
427
428 FcTest *test;
429 FcQual qual;
430 FcOp op;
431 FcExpr *expr;
432 FcEdit *edit;
433 } u;
434 } FcVStack;
435
436 typedef struct _FcConfigParse {
437 FcPStack *pstack;
438 FcVStack *vstack;
439 FcBool error;
440 const FcChar8 *name;
441 FcConfig *config;
442 XML_Parser parser;
443 } FcConfigParse;
444
445 typedef enum _FcConfigSeverity {
446 FcSevereInfo, FcSevereWarning, FcSevereError
447 } FcConfigSeverity;
448
449 static void
450 FcConfigMessage (FcConfigParse *parse, FcConfigSeverity severe, char *fmt, ...)
451 {
452 char *s = "unknown";
453 va_list args;
454
455 va_start (args, fmt);
456
457 switch (severe) {
458 case FcSevereInfo: s = "info"; break;
459 case FcSevereWarning: s = "warning"; break;
460 case FcSevereError: s = "error"; break;
461 }
462 if (parse)
463 {
464 if (parse->name)
465 fprintf (stderr, "Fontconfig %s: \"%s\", line %d: ", s,
466 parse->name, XML_GetCurrentLineNumber (parse->parser));
467 else
468 fprintf (stderr, "Fontconfig %s: line %d: ", s,
469 XML_GetCurrentLineNumber (parse->parser));
470 if (severe >= FcSevereError)
471 parse->error = FcTrue;
472 }
473 else
474 fprintf (stderr, "Fontconfig %s: ", s);
475 vfprintf (stderr, fmt, args);
476 fprintf (stderr, "\n");
477 va_end (args);
478 }
479
480 static void
481 FcVStackPush (FcConfigParse *parse, FcVStack *vstack)
482 {
483 vstack->prev = parse->vstack;
484 vstack->pstack = parse->pstack ? parse->pstack->prev : 0;
485 parse->vstack = vstack;
486 }
487
488 static FcVStack *
489 FcVStackCreate (void)
490 {
491 FcVStack *new;
492
493 new = malloc (sizeof (FcVStack));
494 if (!new)
495 return 0;
496 new->tag = FcVStackNone;
497 new->prev = 0;
498 return new;
499 }
500
501 static void
502 FcVStackDestroy (FcVStack *vstack)
503 {
504 FcVStack *prev;
505
506 for (; vstack; vstack = prev)
507 {
508 prev = vstack->prev;
509 switch (vstack->tag) {
510 case FcVStackNone:
511 break;
512 case FcVStackString:
513 case FcVStackFamily:
514 case FcVStackField:
515 case FcVStackConstant:
516 FcStrFree (vstack->u.string);
517 break;
518 case FcVStackInteger:
519 case FcVStackDouble:
520 break;
521 case FcVStackMatrix:
522 FcMatrixFree (vstack->u.matrix);
523 break;
524 case FcVStackBool:
525 break;
526 case FcVStackTest:
527 FcTestDestroy (vstack->u.test);
528 break;
529 case FcVStackExpr:
530 case FcVStackPrefer:
531 case FcVStackAccept:
532 case FcVStackDefault:
533 FcExprDestroy (vstack->u.expr);
534 break;
535 case FcVStackEdit:
536 FcEditDestroy (vstack->u.edit);
537 break;
538 }
539 free (vstack);
540 }
541 }
542
543 static FcBool
544 FcVStackPushString (FcConfigParse *parse, FcVStackTag tag, FcChar8 *string)
545 {
546 FcVStack *vstack = FcVStackCreate ();
547 if (!vstack)
548 return FcFalse;
549 vstack->u.string = string;
550 vstack->tag = tag;
551 FcVStackPush (parse, vstack);
552 return FcTrue;
553 }
554
555 static FcBool
556 FcVStackPushInteger (FcConfigParse *parse, int integer)
557 {
558 FcVStack *vstack = FcVStackCreate ();
559 if (!vstack)
560 return FcFalse;
561 vstack->u.integer = integer;
562 vstack->tag = FcVStackInteger;
563 FcVStackPush (parse, vstack);
564 return FcTrue;
565 }
566
567 static FcBool
568 FcVStackPushDouble (FcConfigParse *parse, double _double)
569 {
570 FcVStack *vstack = FcVStackCreate ();
571 if (!vstack)
572 return FcFalse;
573 vstack->u._double = _double;
574 vstack->tag = FcVStackDouble;
575 FcVStackPush (parse, vstack);
576 return FcTrue;
577 }
578
579 static FcBool
580 FcVStackPushMatrix (FcConfigParse *parse, FcMatrix *matrix)
581 {
582 FcVStack *vstack = FcVStackCreate ();
583 if (!vstack)
584 return FcFalse;
585 matrix = FcMatrixCopy (matrix);
586 if (!matrix)
587 {
588 FcVStackDestroy (vstack);
589 return FcFalse;
590 }
591 vstack->u.matrix = matrix;
592 vstack->tag = FcVStackMatrix;
593 FcVStackPush (parse, vstack);
594 return FcTrue;
595 }
596
597 static FcBool
598 FcVStackPushBool (FcConfigParse *parse, FcBool bool)
599 {
600 FcVStack *vstack = FcVStackCreate ();
601 if (!vstack)
602 return FcFalse;
603 vstack->u.bool = bool;
604 vstack->tag = FcVStackBool;
605 FcVStackPush (parse, vstack);
606 return FcTrue;
607 }
608
609 static FcBool
610 FcVStackPushTest (FcConfigParse *parse, FcTest *test)
611 {
612 FcVStack *vstack = FcVStackCreate ();
613 if (!vstack)
614 return FcFalse;
615 vstack->u.test = test;
616 vstack->tag = FcVStackTest;
617 FcVStackPush (parse, vstack);
618 return FcTrue;
619 }
620
621 static FcBool
622 FcVStackPushExpr (FcConfigParse *parse, FcVStackTag tag, FcExpr *expr)
623 {
624 FcVStack *vstack = FcVStackCreate ();
625 if (!vstack)
626 return FcFalse;
627 vstack->u.expr = expr;
628 vstack->tag = tag;
629 FcVStackPush (parse, vstack);
630 return FcTrue;
631 }
632
633 static FcBool
634 FcVStackPushEdit (FcConfigParse *parse, FcEdit *edit)
635 {
636 FcVStack *vstack = FcVStackCreate ();
637 if (!vstack)
638 return FcFalse;
639 vstack->u.edit = edit;
640 vstack->tag = FcVStackEdit;
641 FcVStackPush (parse, vstack);
642 return FcTrue;
643 }
644
645 static FcVStack *
646 FcVStackFetch (FcConfigParse *parse, int off)
647 {
648 FcVStack *vstack;
649
650 for (vstack = parse->vstack; vstack && off-- > 0; vstack = vstack->prev);
651 return vstack;
652 }
653
654 static void
655 FcVStackClear (FcConfigParse *parse)
656 {
657 while (parse->vstack && parse->vstack->pstack == parse->pstack)
658 {
659 FcVStack *vstack = parse->vstack;
660 parse->vstack = vstack->prev;
661 vstack->prev = 0;
662 FcVStackDestroy (vstack);
663 }
664 }
665
666 static FcVStack *
667 FcVStackPop (FcConfigParse *parse)
668 {
669 FcVStack *vstack = parse->vstack;
670
671 if (!vstack || vstack->pstack != parse->pstack)
672 return 0;
673 parse->vstack = vstack->prev;
674 vstack->prev = 0;
675 return vstack;
676 }
677
678 static int
679 FcVStackElements (FcConfigParse *parse)
680 {
681 int h = 0;
682 FcVStack *vstack = parse->vstack;
683 while (vstack && vstack->pstack == parse->pstack)
684 {
685 h++;
686 vstack = vstack->prev;
687 }
688 return h;
689 }
690
691 static FcChar8 **
692 FcConfigSaveAttr (const XML_Char **attr)
693 {
694 int n;
695 int slen;
696 int i;
697 FcChar8 **new;
698 FcChar8 *s;
699
700 if (!attr)
701 return 0;
702 slen = 0;
703 for (i = 0; attr[i]; i++)
704 slen += strlen (attr[i]) + 1;
705 n = i;
706 new = malloc ((i + 1) * sizeof (FcChar8 *) + slen);
707 if (!new)
708 return 0;
709 s = (FcChar8 *) (new + (i + 1));
710 for (i = 0; attr[i]; i++)
711 {
712 new[i] = s;
713 strcpy ((char *) s, (char *) attr[i]);
714 s += strlen ((char *) s) + 1;
715 }
716 new[i] = 0;
717 return new;
718 }
719
720 static FcBool
721 FcPStackPush (FcConfigParse *parse, FcElement element, const XML_Char **attr)
722 {
723 FcPStack *new = malloc (sizeof (FcPStack));
724
725 if (!new)
726 return FcFalse;
727 new->prev = parse->pstack;
728 new->element = element;
729 if (attr)
730 {
731 new->attr = FcConfigSaveAttr (attr);
732 if (!new->attr)
733 FcConfigMessage (parse, FcSevereError, "out of memory");
734 }
735 else
736 new->attr = 0;
737 FcStrBufInit (&new->str, 0, 0);
738 parse->pstack = new;
739 return FcTrue;
740 }
741
742 static FcBool
743 FcPStackPop (FcConfigParse *parse)
744 {
745 FcPStack *old;
746
747 if (!parse->pstack)
748 {
749 FcConfigMessage (parse, FcSevereError, "mismatching element");
750 return FcFalse;
751 }
752 FcVStackClear (parse);
753 old = parse->pstack;
754 parse->pstack = old->prev;
755 FcStrBufDestroy (&old->str);
756 if (old->attr)
757 free (old->attr);
758 free (old);
759 return FcTrue;
760 }
761
762 static FcBool
763 FcConfigInit (FcConfigParse *parse, const FcChar8 *name, FcConfig *config, XML_Parser parser)
764 {
765 parse->pstack = 0;
766 parse->vstack = 0;
767 parse->error = FcFalse;
768 parse->name = name;
769 parse->config = config;
770 parse->parser = parser;
771 return FcTrue;
772 }
773
774 static void
775 FcConfigCleanup (FcConfigParse *parse)
776 {
777 while (parse->pstack)
778 FcPStackPop (parse);
779 }
780
781 static const FcChar8 *
782 FcConfigGetAttribute (FcConfigParse *parse, char *attr)
783 {
784 FcChar8 **attrs;
785 if (!parse->pstack)
786 return 0;
787
788 attrs = parse->pstack->attr;
789 while (*attrs)
790 {
791 if (!strcmp ((char *) *attrs, attr))
792 return attrs[1];
793 attrs += 2;
794 }
795 return 0;
796 }
797
798 static void
799 FcStartElement(void *userData, const XML_Char *name, const XML_Char **attr)
800 {
801 FcConfigParse *parse = userData;
802 FcElement element;
803
804 element = FcElementMap (name);
805 if (element == FcElementUnknown)
806 FcConfigMessage (parse, FcSevereWarning, "unknown element \"%s\"", name);
807
808 if (!FcPStackPush (parse, element, attr))
809 {
810 FcConfigMessage (parse, FcSevereError, "out of memory");
811 return;
812 }
813 return;
814 }
815
816 static void
817 FcParseBlank (FcConfigParse *parse)
818 {
819 int n = FcVStackElements (parse);
820 while (n-- > 0)
821 {
822 FcVStack *v = FcVStackFetch (parse, n);
823 if (v->tag != FcVStackInteger)
824 FcConfigMessage (parse, FcSevereError, "non-integer blank");
825 else
826 {
827 if (!parse->config->blanks)
828 {
829 parse->config->blanks = FcBlanksCreate ();
830 if (!parse->config->blanks)
831 {
832 FcConfigMessage (parse, FcSevereError, "out of memory");
833 break;
834 }
835 }
836 if (!FcBlanksAdd (parse->config->blanks, v->u.integer))
837 {
838 FcConfigMessage (parse, FcSevereError, "out of memory");
839 break;
840 }
841 }
842 }
843 }
844
845 static void
846 FcParseRescan (FcConfigParse *parse)
847 {
848 int n = FcVStackElements (parse);
849 while (n-- > 0)
850 {
851 FcVStack *v = FcVStackFetch (parse, n);
852 if (v->tag != FcVStackInteger)
853 FcConfigMessage (parse, FcSevereWarning, "non-integer rescan");
854 else
855 parse->config->rescanInterval = v->u.integer;
856 }
857 }
858
859 static void
860 FcParseInt (FcConfigParse *parse)
861 {
862 FcChar8 *s, *end;
863 int l;
864
865 if (!parse->pstack)
866 return;
867 s = FcStrBufDone (&parse->pstack->str);
868 if (!s)
869 {
870 FcConfigMessage (parse, FcSevereError, "out of memory");
871 return;
872 }
873 end = 0;
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);
877 else
878 FcVStackPushInteger (parse, l);
879 FcStrFree (s);
880 }
881
882 static void
883 FcParseDouble (FcConfigParse *parse)
884 {
885 FcChar8 *s, *end;
886 double d;
887
888 if (!parse->pstack)
889 return;
890 s = FcStrBufDone (&parse->pstack->str);
891 if (!s)
892 {
893 FcConfigMessage (parse, FcSevereError, "out of memory");
894 return;
895 }
896 end = 0;
897 d = strtod ((char *) s, (char **)&end);
898 if (end != s + strlen ((char *) s))
899 FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid double", s);
900 else
901 FcVStackPushDouble (parse, d);
902 FcStrFree (s);
903 }
904
905 static void
906 FcParseString (FcConfigParse *parse, FcVStackTag tag)
907 {
908 FcChar8 *s;
909
910 if (!parse->pstack)
911 return;
912 s = FcStrBufDone (&parse->pstack->str);
913 if (!s)
914 {
915 FcConfigMessage (parse, FcSevereError, "out of memory");
916 return;
917 }
918 if (!FcVStackPushString (parse, tag, s))
919 FcStrFree (s);
920 }
921
922 static void
923 FcParseMatrix (FcConfigParse *parse)
924 {
925 FcVStack *vstack;
926 enum { m_done, m_xx, m_xy, m_yx, m_yy } matrix_state = m_yy;
927 FcMatrix m;
928
929 while ((vstack = FcVStackPop (parse)))
930 {
931 double v;
932 switch (vstack->tag) {
933 case FcVStackInteger:
934 v = vstack->u.integer;
935 break;
936 case FcVStackDouble:
937 v = vstack->u._double;
938 break;
939 default:
940 FcConfigMessage (parse, FcSevereError, "non-double matrix element");
941 v = 1.0;
942 break;
943 }
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;
949 default: break;
950 }
951 matrix_state--;
952 }
953 if (matrix_state != m_done)
954 FcConfigMessage (parse, FcSevereError, "wrong number of matrix elements");
955 else
956 FcVStackPushMatrix (parse, &m);
957 }
958
959 static FcBool
960 FcConfigLexBool (const FcChar8 *bool)
961 {
962 if (*bool == 't' || *bool == 'T')
963 return FcTrue;
964 if (*bool == 'y' || *bool == 'Y')
965 return FcTrue;
966 if (*bool == '1')
967 return FcTrue;
968 return FcFalse;
969 }
970
971 static void
972 FcParseBool (FcConfigParse *parse)
973 {
974 FcChar8 *s;
975
976 if (!parse->pstack)
977 return;
978 s = FcStrBufDone (&parse->pstack->str);
979 if (!s)
980 {
981 FcConfigMessage (parse, FcSevereError, "out of memory");
982 return;
983 }
984 FcVStackPushBool (parse, FcConfigLexBool (s));
985 FcStrFree (s);
986 }
987
988 static void
989 FcParseFamilies (FcConfigParse *parse, FcVStackTag tag)
990 {
991 FcVStack *vstack;
992 FcExpr *left, *expr = 0, *new;
993
994 while ((vstack = FcVStackPop (parse)))
995 {
996 if (vstack->tag != FcVStackFamily)
997 {
998 FcConfigMessage (parse, FcSevereWarning, "non-family");
999 FcVStackDestroy (vstack);
1000 continue;
1001 }
1002 left = vstack->u.expr;
1003 vstack->tag = FcVStackNone;
1004 FcVStackDestroy (vstack);
1005 if (expr)
1006 {
1007 new = FcExprCreateOp (left, FcOpComma, expr);
1008 if (!new)
1009 {
1010 FcConfigMessage (parse, FcSevereError, "out of memory");
1011 FcExprDestroy (left);
1012 FcExprDestroy (expr);
1013 break;
1014 }
1015 expr = new;
1016 }
1017 else
1018 expr = left;
1019 }
1020 if (expr)
1021 {
1022 if (!FcVStackPushExpr (parse, tag, expr))
1023 {
1024 FcConfigMessage (parse, FcSevereError, "out of memory");
1025 if (expr)
1026 FcExprDestroy (expr);
1027 }
1028 }
1029 }
1030
1031 static void
1032 FcParseFamily (FcConfigParse *parse)
1033 {
1034 FcChar8 *s;
1035 FcExpr *expr;
1036
1037 if (!parse->pstack)
1038 return;
1039 s = FcStrBufDone (&parse->pstack->str);
1040 if (!s)
1041 {
1042 FcConfigMessage (parse, FcSevereError, "out of memory");
1043 return;
1044 }
1045 expr = FcExprCreateString (s);
1046 FcStrFree (s);
1047 if (expr)
1048 FcVStackPushExpr (parse, FcVStackFamily, expr);
1049 }
1050
1051 static void
1052 FcParseAlias (FcConfigParse *parse)
1053 {
1054 FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0;
1055 FcEdit *edit = 0, *next;
1056 FcVStack *vstack;
1057 FcTest *test;
1058
1059 while ((vstack = FcVStackPop (parse)))
1060 {
1061 switch (vstack->tag) {
1062 case FcVStackFamily:
1063 if (family)
1064 {
1065 new = FcExprCreateOp (vstack->u.expr, FcOpComma, family);
1066 if (!new)
1067 FcConfigMessage (parse, FcSevereError, "out of memory");
1068 else
1069 family = new;
1070 }
1071 else
1072 new = vstack->u.expr;
1073 if (new)
1074 {
1075 family = new;
1076 vstack->tag = FcVStackNone;
1077 }
1078 break;
1079 case FcVStackPrefer:
1080 if (prefer)
1081 FcExprDestroy (prefer);
1082 prefer = vstack->u.expr;
1083 vstack->tag = FcVStackNone;
1084 break;
1085 case FcVStackAccept:
1086 if (accept)
1087 FcExprDestroy (accept);
1088 accept = vstack->u.expr;
1089 vstack->tag = FcVStackNone;
1090 break;
1091 case FcVStackDefault:
1092 if (def)
1093 FcExprDestroy (def);
1094 def = vstack->u.expr;
1095 vstack->tag = FcVStackNone;
1096 break;
1097 default:
1098 FcConfigMessage (parse, FcSevereWarning, "bad alias");
1099 break;
1100 }
1101 FcVStackDestroy (vstack);
1102 }
1103 if (!family)
1104 {
1105 FcConfigMessage (parse, FcSevereError, "missing family in alias");
1106 if (prefer)
1107 FcExprDestroy (prefer);
1108 if (accept)
1109 FcExprDestroy (accept);
1110 if (def)
1111 FcExprDestroy (def);
1112 return;
1113 }
1114 if (prefer)
1115 {
1116 edit = FcEditCreate (FcConfigSaveField ("family"),
1117 FcOpPrepend,
1118 prefer);
1119 if (edit)
1120 edit->next = 0;
1121 else
1122 FcExprDestroy (prefer);
1123 }
1124 if (accept)
1125 {
1126 next = edit;
1127 edit = FcEditCreate (FcConfigSaveField ("family"),
1128 FcOpAppend,
1129 accept);
1130 if (edit)
1131 edit->next = next;
1132 else
1133 FcExprDestroy (accept);
1134 }
1135 if (def)
1136 {
1137 next = edit;
1138 edit = FcEditCreate (FcConfigSaveField ("family"),
1139 FcOpAppendLast,
1140 def);
1141 if (edit)
1142 edit->next = next;
1143 else
1144 FcExprDestroy (def);
1145 }
1146 if (edit)
1147 {
1148 test = FcTestCreate (FcQualAny,
1149 (FcChar8 *) FC_FAMILY,
1150 FcOpEqual,
1151 family);
1152 if (test)
1153 if (!FcConfigAddEdit (parse->config, test, edit, FcMatchPattern))
1154 FcTestDestroy (test);
1155 }
1156 else
1157 FcExprDestroy (family);
1158 }
1159
1160 static FcExpr *
1161 FcPopExpr (FcConfigParse *parse)
1162 {
1163 FcVStack *vstack = FcVStackPop (parse);
1164 FcExpr *expr = 0;
1165 if (!vstack)
1166 return 0;
1167 switch (vstack->tag) {
1168 case FcVStackNone:
1169 break;
1170 case FcVStackString:
1171 case FcVStackFamily:
1172 expr = FcExprCreateString (vstack->u.string);
1173 break;
1174 case FcVStackField:
1175 expr = FcExprCreateField ((char *) vstack->u.string);
1176 break;
1177 case FcVStackConstant:
1178 expr = FcExprCreateConst (vstack->u.string);
1179 break;
1180 case FcVStackPrefer:
1181 case FcVStackAccept:
1182 case FcVStackDefault:
1183 expr = vstack->u.expr;
1184 vstack->tag = FcVStackNone;
1185 break;
1186 case FcVStackInteger:
1187 expr = FcExprCreateInteger (vstack->u.integer);
1188 break;
1189 case FcVStackDouble:
1190 expr = FcExprCreateDouble (vstack->u._double);
1191 break;
1192 case FcVStackMatrix:
1193 expr = FcExprCreateMatrix (vstack->u.matrix);
1194 break;
1195 case FcVStackBool:
1196 expr = FcExprCreateBool (vstack->u.bool);
1197 break;
1198 case FcVStackTest:
1199 break;
1200 case FcVStackExpr:
1201 expr = vstack->u.expr;
1202 vstack->tag = FcVStackNone;
1203 break;
1204 case FcVStackEdit:
1205 break;
1206 }
1207 FcVStackDestroy (vstack);
1208 return expr;
1209 }
1210
1211 static FcExpr *
1212 FcPopExprs (FcConfigParse *parse, FcOp op)
1213 {
1214 FcExpr *left, *expr = 0, *new;
1215
1216 while ((left = FcPopExpr (parse)))
1217 {
1218 if (expr)
1219 {
1220 new = FcExprCreateOp (left, op, expr);
1221 if (!new)
1222 {
1223 FcConfigMessage (parse, FcSevereError, "out of memory");
1224 FcExprDestroy (left);
1225 FcExprDestroy (expr);
1226 break;
1227 }
1228 expr = new;
1229 }
1230 else
1231 expr = left;
1232 }
1233 return expr;
1234 }
1235
1236 static void
1237 FcParseExpr (FcConfigParse *parse, FcOp op)
1238 {
1239 FcExpr *expr = FcPopExprs (parse, op);
1240 if (expr)
1241 FcVStackPushExpr (parse, FcVStackExpr, expr);
1242 }
1243
1244 static void
1245 FcParseInclude (FcConfigParse *parse)
1246 {
1247 FcChar8 *s;
1248 const FcChar8 *i;
1249 FcBool ignore_missing = FcFalse;
1250
1251 s = FcStrBufDone (&parse->pstack->str);
1252 if (!s)
1253 {
1254 FcConfigMessage (parse, FcSevereError, "out of memory");
1255 return;
1256 }
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;
1262 free (s);
1263 }
1264
1265 typedef struct _FcOpMap {
1266 char *name;
1267 FcOp op;
1268 } FcOpMap;
1269
1270 static FcOp
1271 FcConfigLexOp (const FcChar8 *op, const FcOpMap *map, int nmap)
1272 {
1273 int i;
1274
1275 for (i = 0; i < nmap; i++)
1276 if (!strcmp ((char *) op, map[i].name))
1277 return map[i].op;
1278 return FcOpInvalid;
1279 }
1280
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 }
1288 };
1289
1290 #define NUM_COMPARE_OPS (sizeof fcCompareOps / sizeof fcCompareOps[0])
1291
1292 static FcOp
1293 FcConfigLexCompare (const FcChar8 *compare)
1294 {
1295 return FcConfigLexOp (compare, fcCompareOps, NUM_COMPARE_OPS);
1296 }
1297
1298
1299 static void
1300 FcParseTest (FcConfigParse *parse)
1301 {
1302 const FcChar8 *qual_string;
1303 FcQual qual;
1304 const FcChar8 *name;
1305 const FcChar8 *compare_string;
1306 FcOp compare;
1307 FcExpr *expr;
1308 FcTest *test;
1309
1310 qual_string = FcConfigGetAttribute (parse, "qual");
1311 if (!qual_string)
1312 qual = FcQualAny;
1313 else
1314 {
1315 if (!strcmp ((char *) qual_string, "any"))
1316 qual = FcQualAny;
1317 else if (!strcmp ((char *) qual_string, "all"))
1318 qual = FcQualAll;
1319 else
1320 {
1321 FcConfigMessage (parse, FcSevereWarning, "invalid test qual \"%s\"", qual_string);
1322 qual = FcQualAny;
1323 }
1324 }
1325 name = FcConfigGetAttribute (parse, "name");
1326 if (!name)
1327 {
1328 FcConfigMessage (parse, FcSevereWarning, "missing test name");
1329 name = (FcChar8 *) FC_FAMILY;
1330 }
1331 compare_string = FcConfigGetAttribute (parse, "compare");
1332 if (!compare_string)
1333 compare = FcOpEqual;
1334 else
1335 {
1336 compare = FcConfigLexCompare (compare_string);
1337 if (compare == FcOpInvalid)
1338 {
1339 FcConfigMessage (parse, FcSevereWarning, "invalid test compare \"%s\"", compare_string);
1340 compare = FcOpEqual;
1341 }
1342 }
1343 expr = FcPopExprs (parse, FcOpComma);
1344 if (!expr)
1345 {
1346 FcConfigMessage (parse, FcSevereWarning, "missing test expression");
1347 return;
1348 }
1349 test = FcTestCreate (qual, name, compare, expr);
1350 if (!test)
1351 {
1352 FcConfigMessage (parse, FcSevereError, "out of memory");
1353 return;
1354 }
1355 FcVStackPushTest (parse, test);
1356 }
1357
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 },
1365 };
1366
1367 #define NUM_MODE_OPS (sizeof fcModeOps / sizeof fcModeOps[0])
1368
1369 static FcOp
1370 FcConfigLexMode (const FcChar8 *mode)
1371 {
1372 return FcConfigLexOp (mode, fcModeOps, NUM_MODE_OPS);
1373 }
1374
1375 static void
1376 FcParseEdit (FcConfigParse *parse)
1377 {
1378 const FcChar8 *name;
1379 const FcChar8 *mode_string;
1380 FcOp mode;
1381 FcExpr *expr;
1382 FcEdit *edit;
1383
1384 name = FcConfigGetAttribute (parse, "name");
1385 if (!name)
1386 {
1387 FcConfigMessage (parse, FcSevereWarning, "missing edit name");
1388 name = (FcChar8 *) FC_FAMILY;
1389 }
1390 mode_string = FcConfigGetAttribute (parse, "mode");
1391 if (!mode_string)
1392 mode = FcOpAssign;
1393 else
1394 {
1395 mode = FcConfigLexMode (mode_string);
1396 if (mode == FcOpInvalid)
1397 {
1398 FcConfigMessage (parse, FcSevereWarning, "invalid edit mode \"%s\"", mode_string);
1399 mode = FcOpAssign;
1400 }
1401 }
1402 expr = FcPopExprs (parse, FcOpComma);
1403 edit = FcEditCreate ((char *) FcStrCopy (name), mode, expr);
1404 if (!edit)
1405 {
1406 FcConfigMessage (parse, FcSevereError, "out of memory");
1407 FcExprDestroy (expr);
1408 return;
1409 }
1410 if (!FcVStackPushEdit (parse, edit))
1411 FcEditDestroy (edit);
1412 }
1413
1414 static void
1415 FcParseMatch (FcConfigParse *parse)
1416 {
1417 const FcChar8 *kind_name;
1418 FcMatchKind kind;
1419 FcTest *test = 0;
1420 FcEdit *edit = 0;
1421 FcVStack *vstack;
1422
1423 kind_name = FcConfigGetAttribute (parse, "target");
1424 if (!kind_name)
1425 kind = FcMatchPattern;
1426 else
1427 {
1428 if (!strcmp ((char *) kind_name, "pattern"))
1429 kind = FcMatchPattern;
1430 else if (!strcmp ((char *) kind_name, "font"))
1431 kind = FcMatchFont;
1432 else
1433 {
1434 FcConfigMessage (parse, FcSevereWarning, "invalid match target \"%s\"", kind_name);
1435 kind = FcMatchPattern;
1436 }
1437 }
1438 while ((vstack = FcVStackPop (parse)))
1439 {
1440 switch (vstack->tag) {
1441 case FcVStackTest:
1442 vstack->u.test->next = test;
1443 test = vstack->u.test;
1444 vstack->tag = FcVStackNone;
1445 break;
1446 case FcVStackEdit:
1447 vstack->u.edit->next = edit;
1448 edit = vstack->u.edit;
1449 vstack->tag = FcVStackNone;
1450 break;
1451 default:
1452 FcConfigMessage (parse, FcSevereWarning, "invalid match element");
1453 break;
1454 }
1455 FcVStackDestroy (vstack);
1456 }
1457 if (!FcConfigAddEdit (parse->config, test, edit, kind))
1458 FcConfigMessage (parse, FcSevereError, "out of memory");
1459 }
1460
1461 static void
1462 FcEndElement(void *userData, const XML_Char *name)
1463 {
1464 FcConfigParse *parse = userData;
1465 FcChar8 *data;
1466
1467 if (!parse->pstack)
1468 return;
1469 switch (parse->pstack->element) {
1470 case FcElementNone:
1471 break;
1472 case FcElementFontconfig:
1473 break;
1474 case FcElementDir:
1475 data = FcStrBufDone (&parse->pstack->str);
1476 if (!data)
1477 {
1478 FcConfigMessage (parse, FcSevereError, "out of memory");
1479 break;
1480 }
1481 if (!FcConfigAddDir (parse->config, data))
1482 FcConfigMessage (parse, FcSevereError, "out of memory");
1483 free (data);
1484 break;
1485 case FcElementCache:
1486 data = FcStrBufDone (&parse->pstack->str);
1487 if (!data)
1488 {
1489 FcConfigMessage (parse, FcSevereError, "out of memory");
1490 break;
1491 }
1492 if (!FcConfigSetCache (parse->config, data))
1493 FcConfigMessage (parse, FcSevereError, "out of memory");
1494 free (data);
1495 break;
1496 case FcElementInclude:
1497 FcParseInclude (parse);
1498 break;
1499 case FcElementConfig:
1500 break;
1501 case FcElementMatch:
1502 FcParseMatch (parse);
1503 break;
1504 case FcElementAlias:
1505 FcParseAlias (parse);
1506 break;
1507
1508 case FcElementBlank:
1509 FcParseBlank (parse);
1510 break;
1511 case FcElementRescan:
1512 FcParseRescan (parse);
1513 break;
1514
1515 case FcElementPrefer:
1516 FcParseFamilies (parse, FcVStackPrefer);
1517 break;
1518 case FcElementAccept:
1519 FcParseFamilies (parse, FcVStackAccept);
1520 break;
1521 case FcElementDefault:
1522 FcParseFamilies (parse, FcVStackDefault);
1523 break;
1524 case FcElementFamily:
1525 FcParseFamily (parse);
1526 break;
1527
1528 case FcElementTest:
1529 FcParseTest (parse);
1530 break;
1531 case FcElementEdit:
1532 FcParseEdit (parse);
1533 break;
1534
1535 case FcElementInt:
1536 FcParseInt (parse);
1537 break;
1538 case FcElementDouble:
1539 FcParseDouble (parse);
1540 break;
1541 case FcElementString:
1542 FcParseString (parse, FcVStackString);
1543 break;
1544 case FcElementMatrix:
1545 FcParseMatrix (parse);
1546 break;
1547 case FcElementBool:
1548 FcParseBool (parse);
1549 break;
1550 case FcElementCharset:
1551 /* FcParseCharset (parse); */
1552 break;
1553
1554 case FcElementName:
1555 FcParseString (parse, FcVStackField);
1556 break;
1557 case FcElementConst:
1558 FcParseString (parse, FcVStackConstant);
1559 break;
1560 case FcElementOr:
1561 FcParseExpr (parse, FcOpOr);
1562 break;
1563 case FcElementAnd:
1564 FcParseExpr (parse, FcOpAnd);
1565 break;
1566 case FcElementEq:
1567 FcParseExpr (parse, FcOpEqual);
1568 break;
1569 case FcElementNotEq:
1570 FcParseExpr (parse, FcOpNotEqual);
1571 break;
1572 case FcElementLess:
1573 FcParseExpr (parse, FcOpLess);
1574 break;
1575 case FcElementLessEq:
1576 FcParseExpr (parse, FcOpLessEqual);
1577 break;
1578 case FcElementMore:
1579 FcParseExpr (parse, FcOpMore);
1580 break;
1581 case FcElementMoreEq:
1582 FcParseExpr (parse, FcOpMoreEqual);
1583 break;
1584 case FcElementPlus:
1585 FcParseExpr (parse, FcOpPlus);
1586 break;
1587 case FcElementMinus:
1588 FcParseExpr (parse, FcOpMinus);
1589 break;
1590 case FcElementTimes:
1591 FcParseExpr (parse, FcOpTimes);
1592 break;
1593 case FcElementDivide:
1594 FcParseExpr (parse, FcOpDivide);
1595 break;
1596 case FcElementNot:
1597 FcParseExpr (parse, FcOpNot);
1598 break;
1599 case FcElementIf:
1600 FcParseExpr (parse, FcOpQuest);
1601 break;
1602 case FcElementUnknown:
1603 break;
1604 }
1605 (void) FcPStackPop (parse);
1606 }
1607
1608 static void
1609 FcCharacterData (void *userData, const XML_Char *s, int len)
1610 {
1611 FcConfigParse *parse = userData;
1612
1613 if (!parse->pstack)
1614 return;
1615 if (!FcStrBufData (&parse->pstack->str, (FcChar8 *) s, len))
1616 FcConfigMessage (parse, FcSevereError, "out of memory");
1617 }
1618
1619 static void
1620 FcStartDoctypeDecl (void *userData,
1621 const XML_Char *doctypeName,
1622 const XML_Char *sysid,
1623 const XML_Char *pubid,
1624 int has_internal_subset)
1625 {
1626 FcConfigParse *parse = userData;
1627
1628 if (strcmp ((char *) doctypeName, "fontconfig") != 0)
1629 FcConfigMessage (parse, FcSevereError, "invalid doctype \"%s\"", doctypeName);
1630 }
1631
1632 static void
1633 FcEndDoctypeDecl (void *userData)
1634 {
1635 }
1636
1637 FcBool
1638 FcConfigParseAndLoad (FcConfig *config,
1639 const FcChar8 *name,
1640 FcBool complain)
1641 {
1642
1643 XML_Parser p;
1644 FcChar8 *filename;
1645 FILE *f;
1646 int len;
1647 void *buf;
1648 FcConfigParse parse;
1649 FcBool error = FcTrue;
1650
1651 filename = FcConfigFilename (name);
1652 if (!filename)
1653 goto bail0;
1654 f = fopen ((char *) filename, "r");
1655 free (filename);
1656 if (!f)
1657 goto bail0;
1658
1659 p = XML_ParserCreate ("UTF-8");
1660 if (!p)
1661 goto bail1;
1662
1663 if (!FcConfigInit (&parse, name, config, p))
1664 goto bail2;
1665
1666 XML_SetUserData (p, &parse);
1667
1668 XML_SetDoctypeDeclHandler (p, FcStartDoctypeDecl, FcEndDoctypeDecl);
1669 XML_SetElementHandler (p, FcStartElement, FcEndElement);
1670 XML_SetCharacterDataHandler (p, FcCharacterData);
1671
1672 do {
1673 buf = XML_GetBuffer (p, BUFSIZ);
1674 if (!buf)
1675 {
1676 FcConfigMessage (&parse, FcSevereError, "cannot get parse buffer");
1677 goto bail3;
1678 }
1679 len = fread (buf, 1, BUFSIZ, f);
1680 if (len < 0)
1681 {
1682 FcConfigMessage (&parse, FcSevereError, "failed reading config file");
1683 goto bail3;
1684 }
1685 if (!XML_ParseBuffer (p, len, len == 0))
1686 {
1687 FcConfigMessage (&parse, FcSevereError, "%s",
1688 XML_ErrorString (XML_GetErrorCode (p)));
1689 goto bail3;
1690 }
1691 } while (len != 0);
1692 error = parse.error;
1693 bail3:
1694 FcConfigCleanup (&parse);
1695 bail2:
1696 XML_ParserFree (p);
1697 bail1:
1698 fclose (f);
1699 bail0:
1700 if (error && complain)
1701 {
1702 if (name)
1703 FcConfigMessage (0, FcSevereError, "Cannot load config file \"%s\"", name);
1704 else
1705 FcConfigMessage (0, FcSevereError, "Cannot load default config file");
1706 return FcFalse;
1707 }
1708 return FcTrue;
1709 }