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