1 /*
2 * fontconfig/src/fcname.c
3 *
4 * Copyright © 2000 Keith Packard
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 the author(s) not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. The authors make 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 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL THE AUTHOR(S) 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 "fcint.h"
26 #include <ctype.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdio.h>
30
31 static const FcObjectType FcObjects[] = {
32 #define FC_OBJECT(NAME, Type, Cmp) { FC_##NAME, Type },
33 #include "fcobjs.h"
34 #undef FC_OBJECT
35 };
36
37 #define NUM_OBJECT_TYPES ((int) (sizeof FcObjects / sizeof FcObjects[0]))
38
39 static const FcObjectType *
40 FcObjectFindById (FcObject object)
41 {
42 if (1 <= object && object <= NUM_OBJECT_TYPES)
43 return &FcObjects[object - 1];
44 return FcObjectLookupOtherTypeById (object);
45 }
46
47 FcBool
48 FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
49 {
50 /* Deprecated. */
51 return FcFalse;
52 }
53
54 FcBool
55 FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
56 {
57 /* Deprecated. */
58 return FcFalse;
59 }
60
61 const FcObjectType *
62 FcNameGetObjectType (const char *object)
63 {
64 int id = FcObjectLookupBuiltinIdByName (object);
65
66 if (!id)
67 return FcObjectLookupOtherTypeByName (object);
68
69 return &FcObjects[id - 1];
70 }
71
72 FcBool
73 FcObjectValidType (FcObject object, FcType type)
74 {
75 const FcObjectType *t = FcObjectFindById (object);
76
77 if (t) {
78 switch ((int) t->type) {
79 case FcTypeUnknown:
80 return FcTrue;
81 case FcTypeDouble:
82 case FcTypeInteger:
83 if (type == FcTypeDouble || type == FcTypeInteger)
84 return FcTrue;
85 break;
86 case FcTypeLangSet:
87 if (type == FcTypeLangSet || type == FcTypeString)
88 return FcTrue;
89 break;
90 case FcTypeRange:
91 if (type == FcTypeRange ||
92 type == FcTypeDouble ||
93 type == FcTypeInteger)
94 return FcTrue;
95 break;
96 default:
97 if (type == t->type)
98 return FcTrue;
99 break;
100 }
101 return FcFalse;
102 }
103 return FcTrue;
104 }
105
106 FcObject
107 FcObjectFromName (const char * name)
108 {
109 return FcObjectLookupIdByName (name);
110 }
111
112 FcObjectSet *
113 FcObjectGetSet (void)
114 {
115 int i;
116 FcObjectSet *os = NULL;
117
118
119 os = FcObjectSetCreate ();
120 for (i = 0; i < NUM_OBJECT_TYPES; i++)
121 FcObjectSetAdd (os, FcObjects[i].object);
122
123 return os;
124 }
125
126 const char *
127 FcObjectName (FcObject object)
128 {
129 const FcObjectType *o = FcObjectFindById (object);
130
131 if (o)
132 return o->object;
133
134 return FcObjectLookupOtherNameById (object);
135 }
136
137 static const FcConstant _FcBaseConstants[] = {
138 { (FcChar8 *) "thin", "weight", FC_WEIGHT_THIN, },
139 { (FcChar8 *) "extralight", "weight", FC_WEIGHT_EXTRALIGHT, },
140 { (FcChar8 *) "ultralight", "weight", FC_WEIGHT_EXTRALIGHT, },
141 { (FcChar8 *) "demilight", "weight", FC_WEIGHT_DEMILIGHT, },
142 { (FcChar8 *) "semilight", "weight", FC_WEIGHT_DEMILIGHT, },
143 { (FcChar8 *) "light", "weight", FC_WEIGHT_LIGHT, },
144 { (FcChar8 *) "book", "weight", FC_WEIGHT_BOOK, },
145 { (FcChar8 *) "regular", "weight", FC_WEIGHT_REGULAR, },
146 { (FcChar8 *) "normal", "weight", FC_WEIGHT_NORMAL, },
147 { (FcChar8 *) "medium", "weight", FC_WEIGHT_MEDIUM, },
148 { (FcChar8 *) "demibold", "weight", FC_WEIGHT_DEMIBOLD, },
149 { (FcChar8 *) "semibold", "weight", FC_WEIGHT_DEMIBOLD, },
150 { (FcChar8 *) "bold", "weight", FC_WEIGHT_BOLD, },
151 { (FcChar8 *) "extrabold", "weight", FC_WEIGHT_EXTRABOLD, },
152 { (FcChar8 *) "ultrabold", "weight", FC_WEIGHT_EXTRABOLD, },
153 { (FcChar8 *) "black", "weight", FC_WEIGHT_BLACK, },
154 { (FcChar8 *) "heavy", "weight", FC_WEIGHT_HEAVY, },
155 { (FcChar8 *) "extrablack", "weight", FC_WEIGHT_EXTRABLACK, },
156 { (FcChar8 *) "ultrablack", "weight", FC_WEIGHT_ULTRABLACK, },
157
158 { (FcChar8 *) "roman", "slant", FC_SLANT_ROMAN, },
159 { (FcChar8 *) "italic", "slant", FC_SLANT_ITALIC, },
160 { (FcChar8 *) "oblique", "slant", FC_SLANT_OBLIQUE, },
161
162 { (FcChar8 *) "ultracondensed", "width", FC_WIDTH_ULTRACONDENSED },
163 { (FcChar8 *) "extracondensed", "width", FC_WIDTH_EXTRACONDENSED },
164 { (FcChar8 *) "condensed", "width", FC_WIDTH_CONDENSED },
165 { (FcChar8 *) "semicondensed", "width", FC_WIDTH_SEMICONDENSED },
166 { (FcChar8 *) "normal", "width", FC_WIDTH_NORMAL },
167 { (FcChar8 *) "semiexpanded", "width", FC_WIDTH_SEMIEXPANDED },
168 { (FcChar8 *) "expanded", "width", FC_WIDTH_EXPANDED },
169 { (FcChar8 *) "extraexpanded", "width", FC_WIDTH_EXTRAEXPANDED },
170 { (FcChar8 *) "ultraexpanded", "width", FC_WIDTH_ULTRAEXPANDED },
171
172 { (FcChar8 *) "proportional", "spacing", FC_PROPORTIONAL, },
173 { (FcChar8 *) "dual", "spacing", FC_DUAL, },
174 { (FcChar8 *) "mono", "spacing", FC_MONO, },
175 { (FcChar8 *) "charcell", "spacing", FC_CHARCELL, },
176
177 { (FcChar8 *) "unknown", "rgba", FC_RGBA_UNKNOWN },
178 { (FcChar8 *) "rgb", "rgba", FC_RGBA_RGB, },
179 { (FcChar8 *) "bgr", "rgba", FC_RGBA_BGR, },
180 { (FcChar8 *) "vrgb", "rgba", FC_RGBA_VRGB },
181 { (FcChar8 *) "vbgr", "rgba", FC_RGBA_VBGR },
182 { (FcChar8 *) "none", "rgba", FC_RGBA_NONE },
183
184 { (FcChar8 *) "hintnone", "hintstyle", FC_HINT_NONE },
185 { (FcChar8 *) "hintslight", "hintstyle", FC_HINT_SLIGHT },
186 { (FcChar8 *) "hintmedium", "hintstyle", FC_HINT_MEDIUM },
187 { (FcChar8 *) "hintfull", "hintstyle", FC_HINT_FULL },
188
189 { (FcChar8 *) "antialias", "antialias", FcTrue },
190 { (FcChar8 *) "hinting", "hinting", FcTrue },
191 { (FcChar8 *) "verticallayout", "verticallayout", FcTrue },
192 { (FcChar8 *) "autohint", "autohint", FcTrue },
193 { (FcChar8 *) "globaladvance", "globaladvance", FcTrue }, /* deprecated */
194 { (FcChar8 *) "outline", "outline", FcTrue },
195 { (FcChar8 *) "scalable", "scalable", FcTrue },
196 { (FcChar8 *) "minspace", "minspace", FcTrue },
197 { (FcChar8 *) "embolden", "embolden", FcTrue },
198 { (FcChar8 *) "embeddedbitmap", "embeddedbitmap", FcTrue },
199 { (FcChar8 *) "decorative", "decorative", FcTrue },
200 { (FcChar8 *) "lcdnone", "lcdfilter", FC_LCD_NONE },
201 { (FcChar8 *) "lcddefault", "lcdfilter", FC_LCD_DEFAULT },
202 { (FcChar8 *) "lcdlight", "lcdfilter", FC_LCD_LIGHT },
203 { (FcChar8 *) "lcdlegacy", "lcdfilter", FC_LCD_LEGACY },
204 };
205
206 #define NUM_FC_CONSTANTS (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])
207
208 FcBool
209 FcNameRegisterConstants (const FcConstant *consts, int nconsts)
210 {
211 /* Deprecated. */
212 return FcFalse;
213 }
214
215 FcBool
216 FcNameUnregisterConstants (const FcConstant *consts, int nconsts)
217 {
218 /* Deprecated. */
219 return FcFalse;
220 }
221
222 const FcConstant *
223 FcNameGetConstant (const FcChar8 *string)
224 {
225 unsigned int i;
226
227 for (i = 0; i < NUM_FC_CONSTANTS; i++)
228 if (!FcStrCmpIgnoreCase (string, _FcBaseConstants[i].name))
229 return &_FcBaseConstants[i];
230
231 return 0;
232 }
233
234 const FcConstant *
235 FcNameGetConstantFor (const FcChar8 *string, const char *object)
236 {
237 unsigned int i;
238
239 for (i = 0; i < NUM_FC_CONSTANTS; i++)
240 if (!FcStrCmpIgnoreCase (string, _FcBaseConstants[i].name) &&
241 !FcStrCmpIgnoreCase ((const FcChar8 *)object, (const FcChar8 *)_FcBaseConstants[i].object))
242 return &_FcBaseConstants[i];
243
244 return 0;
245 }
246
247 FcBool
248 FcNameConstant (const FcChar8 *string, int *result)
249 {
250 const FcConstant *c;
251
252 if ((c = FcNameGetConstant(string)))
253 {
254 *result = c->value;
255 return FcTrue;
256 }
257 return FcFalse;
258 }
259
260 FcBool
261 FcNameConstantWithObjectCheck (const FcChar8 *string, const char *object, int *result)
262 {
263 const FcConstant *c;
264
265 if ((c = FcNameGetConstantFor(string, object)))
266 {
267 *result = c->value;
268 return FcTrue;
269 }
270 else if ((c = FcNameGetConstant(string)))
271 {
272 if (strcmp (c->object, object) != 0)
273 {
274 fprintf (stderr, "Fontconfig error: Unexpected constant name `%s' used for object `%s': should be `%s'\n", string, object, c->object);
275 return FcFalse;
276 }
277 /* Unlikely to reach out */
278 *result = c->value;
279 return FcTrue;
280 }
281 return FcFalse;
282 }
283
284 FcBool
285 FcNameBool (const FcChar8 *v, FcBool *result)
286 {
287 char c0, c1;
288
289 c0 = *v;
290 c0 = FcToLower (c0);
291 if (c0 == 't' || c0 == 'y' || c0 == '1')
292 {
293 *result = FcTrue;
294 return FcTrue;
295 }
296 if (c0 == 'f' || c0 == 'n' || c0 == '0')
297 {
298 *result = FcFalse;
299 return FcTrue;
300 }
301 if (c0 == 'd' || c0 == 'x' || c0 == '2')
302 {
303 *result = FcDontCare;
304 return FcTrue;
305 }
306 if (c0 == 'o')
307 {
308 c1 = v[1];
309 c1 = FcToLower (c1);
310 if (c1 == 'n')
311 {
312 *result = FcTrue;
313 return FcTrue;
314 }
315 if (c1 == 'f')
316 {
317 *result = FcFalse;
318 return FcTrue;
319 }
320 if (c1 == 'r')
321 {
322 *result = FcDontCare;
323 return FcTrue;
324 }
325 }
326 return FcFalse;
327 }
328
329 static FcValue
330 FcNameConvert (FcType type, const char *object, FcChar8 *string)
331 {
332 FcValue v;
333 FcMatrix m;
334 double b, e;
335 char *p;
336
337 v.type = type;
338 switch ((int) v.type) {
339 case FcTypeInteger:
340 if (!FcNameConstantWithObjectCheck (string, object, &v.u.i))
341 v.u.i = atoi ((char *) string);
342 break;
343 case FcTypeString:
344 v.u.s = FcStrdup (string);
345 if (!v.u.s)
346 v.type = FcTypeVoid;
347 break;
348 case FcTypeBool:
349 if (!FcNameBool (string, &v.u.b))
350 v.u.b = FcFalse;
351 break;
352 case FcTypeDouble:
353 v.u.d = strtod ((char *) string, 0);
354 break;
355 case FcTypeMatrix:
356 FcMatrixInit (&m);
357 sscanf ((char *) string, "%lg %lg %lg %lg", &m.xx, &m.xy, &m.yx, &m.yy);
358 v.u.m = FcMatrixCopy (&m);
359 break;
360 case FcTypeCharSet:
361 v.u.c = FcNameParseCharSet (string);
362 if (!v.u.c)
363 v.type = FcTypeVoid;
364 break;
365 case FcTypeLangSet:
366 v.u.l = FcNameParseLangSet (string);
367 if (!v.u.l)
368 v.type = FcTypeVoid;
369 break;
370 case FcTypeRange:
371 if (sscanf ((char *) string, "[%lg %lg]", &b, &e) != 2)
372 {
373 char *sc, *ec;
374 size_t len = strlen ((const char *) string);
375 int si, ei;
376
377 sc = malloc (len + 1);
378 ec = malloc (len + 1);
379 if (sc && ec && sscanf ((char *) string, "[%s %[^]]]", sc, ec) == 2)
380 {
381 if (FcNameConstantWithObjectCheck ((const FcChar8 *) sc, object, &si) &&
382 FcNameConstantWithObjectCheck ((const FcChar8 *) ec, object, &ei))
383 v.u.r = FcRangeCreateDouble (si, ei);
384 else
385 goto bail1;
386 }
387 else
388 {
389 bail1:
390 v.type = FcTypeDouble;
391 if (FcNameConstantWithObjectCheck (string, object, &si))
392 {
393 v.u.d = (double) si;
394 } else {
395 v.u.d = strtod ((char *) string, &p);
396 if (p != NULL && p[0] != 0)
397 v.type = FcTypeVoid;
398 }
399 }
400 if (sc)
401 free (sc);
402 if (ec)
403 free (ec);
404 }
405 else
406 v.u.r = FcRangeCreateDouble (b, e);
407 break;
408 default:
409 break;
410 }
411 return v;
412 }
413
414 static const FcChar8 *
415 FcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *last)
416 {
417 FcChar8 c;
418
419 while ((c = *cur))
420 {
421 if (!isspace (c))
422 break;
423 ++cur;
424 }
425 while ((c = *cur))
426 {
427 if (c == '\\')
428 {
429 ++cur;
430 if (!(c = *cur))
431 break;
432 }
433 else if (strchr (delim, c))
434 break;
435 ++cur;
436 *save++ = c;
437 }
438 *save = 0;
439 *last = *cur;
440 if (*cur)
441 cur++;
442 return cur;
443 }
444
445 FcPattern *
446 FcNameParse (const FcChar8 *name)
447 {
448 FcChar8 *save;
449 FcPattern *pat;
450 double d;
451 FcChar8 *e;
452 FcChar8 delim;
453 FcValue v;
454 const FcObjectType *t;
455 const FcConstant *c;
456
457 /* freed below */
458 save = malloc (strlen ((char *) name) + 1);
459 if (!save)
460 goto bail0;
461 pat = FcPatternCreate ();
462 if (!pat)
463 goto bail1;
464
465 for (;;)
466 {
467 name = FcNameFindNext (name, "-,:", save, &delim);
468 if (save[0])
469 {
470 if (!FcPatternObjectAddString (pat, FC_FAMILY_OBJECT, save))
471 goto bail2;
472 }
473 if (delim != ',')
474 break;
475 }
476 if (delim == '-')
477 {
478 for (;;)
479 {
480 name = FcNameFindNext (name, "-,:", save, &delim);
481 d = strtod ((char *) save, (char **) &e);
482 if (e != save)
483 {
484 if (!FcPatternObjectAddDouble (pat, FC_SIZE_OBJECT, d))
485 goto bail2;
486 }
487 if (delim != ',')
488 break;
489 }
490 }
491 while (delim == ':')
492 {
493 name = FcNameFindNext (name, "=_:", save, &delim);
494 if (save[0])
495 {
496 if (delim == '=' || delim == '_')
497 {
498 t = FcNameGetObjectType ((char *) save);
499 for (;;)
500 {
501 name = FcNameFindNext (name, ":,", save, &delim);
502 if (t)
503 {
504 v = FcNameConvert (t->type, t->object, save);
505 if (!FcPatternAdd (pat, t->object, v, FcTrue))
506 {
507 FcValueDestroy (v);
508 goto bail2;
509 }
510 FcValueDestroy (v);
511 }
512 if (delim != ',')
513 break;
514 }
515 }
516 else
517 {
518 if ((c = FcNameGetConstant (save)))
519 {
520 t = FcNameGetObjectType ((char *) c->object);
521 if (t == NULL)
522 goto bail2;
523 switch ((int) t->type) {
524 case FcTypeInteger:
525 case FcTypeDouble:
526 if (!FcPatternAddInteger (pat, c->object, c->value))
527 goto bail2;
528 break;
529 case FcTypeBool:
530 if (!FcPatternAddBool (pat, c->object, c->value))
531 goto bail2;
532 break;
533 case FcTypeRange:
534 if (!FcPatternAddInteger (pat, c->object, c->value))
535 goto bail2;
536 break;
537 default:
538 break;
539 }
540 }
541 }
542 }
543 }
544
545 free (save);
546 return pat;
547
548 bail2:
549 FcPatternDestroy (pat);
550 bail1:
551 free (save);
552 bail0:
553 return 0;
554 }
555 static FcBool
556 FcNameUnparseString (FcStrBuf *buf,
557 const FcChar8 *string,
558 const FcChar8 *escape)
559 {
560 FcChar8 c;
561 while ((c = *string++))
562 {
563 if (escape && strchr ((char *) escape, (char) c))
564 {
565 if (!FcStrBufChar (buf, escape[0]))
566 return FcFalse;
567 }
568 if (!FcStrBufChar (buf, c))
569 return FcFalse;
570 }
571 return FcTrue;
572 }
573
574 FcBool
575 FcNameUnparseValue (FcStrBuf *buf,
576 FcValue *v0,
577 FcChar8 *escape)
578 {
579 FcChar8 temp[1024];
580 FcValue v = FcValueCanonicalize(v0);
581
582 switch (v.type) {
583 case FcTypeUnknown:
584 case FcTypeVoid:
585 return FcTrue;
586 case FcTypeInteger:
587 sprintf ((char *) temp, "%d", v.u.i);
588 return FcNameUnparseString (buf, temp, 0);
589 case FcTypeDouble:
590 sprintf ((char *) temp, "%g", v.u.d);
591 return FcNameUnparseString (buf, temp, 0);
592 case FcTypeString:
593 return FcNameUnparseString (buf, v.u.s, escape);
594 case FcTypeBool:
595 return FcNameUnparseString (buf,
596 v.u.b == FcTrue ? (FcChar8 *) "True" :
597 v.u.b == FcFalse ? (FcChar8 *) "False" :
598 (FcChar8 *) "DontCare", 0);
599 case FcTypeMatrix:
600 sprintf ((char *) temp, "%g %g %g %g",
601 v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
602 return FcNameUnparseString (buf, temp, 0);
603 case FcTypeCharSet:
604 return FcNameUnparseCharSet (buf, v.u.c);
605 case FcTypeLangSet:
606 return FcNameUnparseLangSet (buf, v.u.l);
607 case FcTypeFTFace:
608 return FcTrue;
609 case FcTypeRange:
610 sprintf ((char *) temp, "[%g %g]", v.u.r->begin, v.u.r->end);
611 return FcNameUnparseString (buf, temp, 0);
612 }
613 return FcFalse;
614 }
615
616 FcBool
617 FcNameUnparseValueList (FcStrBuf *buf,
618 FcValueListPtr v,
619 FcChar8 *escape)
620 {
621 while (v)
622 {
623 if (!FcNameUnparseValue (buf, &v->value, escape))
624 return FcFalse;
625 if ((v = FcValueListNext(v)) != NULL)
626 if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
627 return FcFalse;
628 }
629 return FcTrue;
630 }
631
632 #define FC_ESCAPE_FIXED "\\-:,"
633 #define FC_ESCAPE_VARIABLE "\\=_:,"
634
635 FcChar8 *
636 FcNameUnparse (FcPattern *pat)
637 {
638 return FcNameUnparseEscaped (pat, FcTrue);
639 }
640
641 FcChar8 *
642 FcNameUnparseEscaped (FcPattern *pat, FcBool escape)
643 {
644 FcStrBuf buf, buf2;
645 FcChar8 buf_static[8192], buf2_static[256];
646 int i;
647 FcPatternElt *e;
648
649 FcStrBufInit (&buf, buf_static, sizeof (buf_static));
650 FcStrBufInit (&buf2, buf2_static, sizeof (buf2_static));
651 e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT);
652 if (e)
653 {
654 if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
655 goto bail0;
656 }
657 e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT);
658 if (e)
659 {
660 FcChar8 *p;
661
662 if (!FcNameUnparseString (&buf2, (FcChar8 *) "-", 0))
663 goto bail0;
664 if (!FcNameUnparseValueList (&buf2, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
665 goto bail0;
666 p = FcStrBufDoneStatic (&buf2);
667 FcStrBufDestroy (&buf2);
668 if (strlen ((const char *)p) > 1)
669 if (!FcStrBufString (&buf, p))
670 goto bail0;
671 }
672 for (i = 0; i < NUM_OBJECT_TYPES; i++)
673 {
674 FcObject id = i + 1;
675 const FcObjectType *o;
676 o = &FcObjects[i];
677 if (!strcmp (o->object, FC_FAMILY) ||
678 !strcmp (o->object, FC_SIZE))
679 continue;
680
681 e = FcPatternObjectFindElt (pat, id);
682 if (e)
683 {
684 if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
685 goto bail0;
686 if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
687 goto bail0;
688 if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
689 goto bail0;
690 if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ?
691 (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
692 goto bail0;
693 }
694 }
695 return FcStrBufDone (&buf);
696 bail0:
697 FcStrBufDestroy (&buf);
698 return 0;
699 }
700 #define __fcname__
701 #include "fcaliastail.h"
702 #undef __fcname__