Avoid null pointer dereference in FcNameParse if malloc fails
[platform/upstream/fontconfig.git] / src / fcname.c
index 9f677a8..f302948 100644 (file)
 /*
- * $XFree86: xc/lib/fontconfig/src/fcname.c,v 1.6 2002/06/02 21:07:57 keithp Exp $
+ * fontconfig/src/fcname.c
  *
- * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
+ * Copyright © 2000 Keith Packard
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
  * the above copyright notice appear in all copies and that both that
  * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
+ * documentation, and that the name of the author(s) not be used in
  * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission.  Keith Packard makes no
+ * specific, written prior permission.  The authors make no
  * representations about the suitability of this software for any purpose.  It
  * is provided "as is" without express or implied warranty.
  *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include "fcint.h"
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
-#include "fcint.h"
 
-static const FcObjectType _FcBaseObjectTypes[] = {
-    { FC_FAMILY,       FcTypeString, },
-    { FC_STYLE,                FcTypeString, },
-    { FC_SLANT,                FcTypeInteger, },
-    { FC_WEIGHT,       FcTypeInteger, },
-    { FC_SIZE,         FcTypeDouble, },
-    { FC_ASPECT,       FcTypeDouble, },
-    { FC_PIXEL_SIZE,   FcTypeDouble, },
-    { FC_SPACING,      FcTypeInteger, },
-    { FC_FOUNDRY,      FcTypeString, },
-/*    { FC_CORE,               FcTypeBool, }, */
-    { FC_ANTIALIAS,    FcTypeBool, },
-/*    { FC_XLFD,               FcTypeString, }, */
-    { FC_FILE,         FcTypeString, },
-    { FC_INDEX,                FcTypeInteger, },
-    { FC_RASTERIZER,   FcTypeString, },
-    { FC_OUTLINE,      FcTypeBool, },
-    { FC_SCALABLE,     FcTypeBool, },
-    { FC_RGBA,         FcTypeInteger, },
-    { FC_SCALE,                FcTypeDouble, },
-/*    { FC_RENDER,     FcTypeBool, },*/
-    { FC_MINSPACE,     FcTypeBool, },
-    { FC_CHAR_WIDTH,   FcTypeInteger },
-    { FC_CHAR_HEIGHT,  FcTypeInteger },
-    { FC_MATRIX,       FcTypeMatrix },
-    { FC_CHARSET,      FcTypeCharSet },
-    { FC_LANG,         FcTypeString },
+static const FcObjectType FcObjects[] = {
+#define FC_OBJECT(NAME, Type, Cmp) { FC_##NAME, Type },
+#include "fcobjs.h"
+#undef FC_OBJECT
 };
 
-#define NUM_OBJECT_TYPES    (sizeof _FcBaseObjectTypes / sizeof _FcBaseObjectTypes[0])
-
-typedef struct _FcObjectTypeList    FcObjectTypeList;
-
-struct _FcObjectTypeList {
-    const FcObjectTypeList  *next;
-    const FcObjectType     *types;
-    int                            ntypes;
-};
-
-static const FcObjectTypeList _FcBaseObjectTypesList = {
-    0,
-    _FcBaseObjectTypes,
-    NUM_OBJECT_TYPES
-};
+#define NUM_OBJECT_TYPES ((int) (sizeof FcObjects / sizeof FcObjects[0]))
 
-static const FcObjectTypeList  *_FcObjectTypes = &_FcBaseObjectTypesList;
+static const FcObjectType *
+FcObjectFindById (FcObject object)
+{
+    if (1 <= object && object <= NUM_OBJECT_TYPES)
+       return &FcObjects[object - 1];
+    return FcObjectLookupOtherTypeById (object);
+}
 
 FcBool
 FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
 {
-    FcObjectTypeList   *l;
-
-    l = (FcObjectTypeList *) malloc (sizeof (FcObjectTypeList));
-    if (!l)
-       return FcFalse;
-    l->types = types;
-    l->ntypes = ntypes;
-    l->next = _FcObjectTypes;
-    _FcObjectTypes = l;
-    return FcTrue;
+    /* Deprecated. */
+    return FcFalse;
 }
 
 FcBool
 FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
 {
-    const FcObjectTypeList     *l, **prev;
-
-    for (prev = &_FcObjectTypes; 
-        (l = *prev); 
-        prev = (const FcObjectTypeList **) &(l->next))
-    {
-       if (l->types == types && l->ntypes == ntypes)
-       {
-           *prev = l->next;
-           free ((void *) l);
-           return FcTrue;
-       }
-    }
+    /* Deprecated. */
     return FcFalse;
 }
 
 const FcObjectType *
 FcNameGetObjectType (const char *object)
 {
-    int                            i;
-    const FcObjectTypeList  *l;
-    const FcObjectType     *t;
-    
-    for (l = _FcObjectTypes; l; l = l->next)
-    {
-       for (i = 0; i < l->ntypes; i++)
-       {
-           t = &l->types[i];
-           if (!strcmp (object, t->object))
-               return t;
+    int id = FcObjectLookupBuiltinIdByName (object);
+
+    if (!id)
+       return FcObjectLookupOtherTypeByName (object);
+
+    return &FcObjects[id - 1];
+}
+
+FcBool
+FcObjectValidType (FcObject object, FcType type)
+{
+    const FcObjectType    *t = FcObjectFindById (object);
+
+    if (t) {
+       switch ((int) t->type) {
+       case FcTypeUnknown:
+           return FcTrue;
+       case FcTypeDouble:
+       case FcTypeInteger:
+           if (type == FcTypeDouble || type == FcTypeInteger)
+               return FcTrue;
+           break;
+       case FcTypeLangSet:
+           if (type == FcTypeLangSet || type == FcTypeString)
+               return FcTrue;
+           break;
+       default:
+           if (type == t->type)
+               return FcTrue;
+           break;
        }
+       return FcFalse;
     }
-    return 0;
+    return FcTrue;
+}
+
+FcObject
+FcObjectFromName (const char * name)
+{
+    return FcObjectLookupIdByName (name);
+}
+
+FcObjectSet *
+FcObjectGetSet (void)
+{
+    int                i;
+    FcObjectSet        *os = NULL;
+
+
+    os = FcObjectSetCreate ();
+    for (i = 0; i < NUM_OBJECT_TYPES; i++)
+       FcObjectSetAdd (os, FcObjects[i].object);
+
+    return os;
+}
+
+const char *
+FcObjectName (FcObject object)
+{
+    const FcObjectType   *o = FcObjectFindById (object);
+
+    if (o)
+       return o->object;
+
+    return FcObjectLookupOtherNameById (object);
 }
 
 static const FcConstant _FcBaseConstants[] = {
+    { (FcChar8 *) "thin",          "weight",   FC_WEIGHT_THIN, },
+    { (FcChar8 *) "extralight",            "weight",   FC_WEIGHT_EXTRALIGHT, },
+    { (FcChar8 *) "ultralight",            "weight",   FC_WEIGHT_EXTRALIGHT, },
     { (FcChar8 *) "light",         "weight",   FC_WEIGHT_LIGHT, },
+    { (FcChar8 *) "book",          "weight",   FC_WEIGHT_BOOK, },
+    { (FcChar8 *) "regular",       "weight",   FC_WEIGHT_REGULAR, },
     { (FcChar8 *) "medium",        "weight",   FC_WEIGHT_MEDIUM, },
     { (FcChar8 *) "demibold",      "weight",   FC_WEIGHT_DEMIBOLD, },
+    { (FcChar8 *) "semibold",      "weight",   FC_WEIGHT_DEMIBOLD, },
     { (FcChar8 *) "bold",          "weight",   FC_WEIGHT_BOLD, },
+    { (FcChar8 *) "extrabold",     "weight",   FC_WEIGHT_EXTRABOLD, },
+    { (FcChar8 *) "ultrabold",     "weight",   FC_WEIGHT_EXTRABOLD, },
     { (FcChar8 *) "black",         "weight",   FC_WEIGHT_BLACK, },
+    { (FcChar8 *) "heavy",         "weight",   FC_WEIGHT_HEAVY, },
 
     { (FcChar8 *) "roman",         "slant",    FC_SLANT_ROMAN, },
     { (FcChar8 *) "italic",        "slant",    FC_SLANT_ITALIC, },
     { (FcChar8 *) "oblique",       "slant",    FC_SLANT_OBLIQUE, },
 
+    { (FcChar8 *) "ultracondensed", "width",   FC_WIDTH_ULTRACONDENSED },
+    { (FcChar8 *) "extracondensed", "width",   FC_WIDTH_EXTRACONDENSED },
+    { (FcChar8 *) "condensed",     "width",    FC_WIDTH_CONDENSED },
+    { (FcChar8 *) "semicondensed",  "width",   FC_WIDTH_SEMICONDENSED },
+    { (FcChar8 *) "normal",        "width",    FC_WIDTH_NORMAL },
+    { (FcChar8 *) "semiexpanded",   "width",   FC_WIDTH_SEMIEXPANDED },
+    { (FcChar8 *) "expanded",      "width",    FC_WIDTH_EXPANDED },
+    { (FcChar8 *) "extraexpanded",  "width",   FC_WIDTH_EXTRAEXPANDED },
+    { (FcChar8 *) "ultraexpanded",  "width",   FC_WIDTH_ULTRAEXPANDED },
+
     { (FcChar8 *) "proportional",   "spacing",  FC_PROPORTIONAL, },
+    { (FcChar8 *) "dual",          "spacing",  FC_DUAL, },
     { (FcChar8 *) "mono",          "spacing",  FC_MONO, },
     { (FcChar8 *) "charcell",      "spacing",  FC_CHARCELL, },
 
+    { (FcChar8 *) "unknown",       "rgba",         FC_RGBA_UNKNOWN },
     { (FcChar8 *) "rgb",           "rgba",         FC_RGBA_RGB, },
     { (FcChar8 *) "bgr",           "rgba",         FC_RGBA_BGR, },
     { (FcChar8 *) "vrgb",          "rgba",         FC_RGBA_VRGB },
     { (FcChar8 *) "vbgr",          "rgba",         FC_RGBA_VBGR },
+    { (FcChar8 *) "none",          "rgba",         FC_RGBA_NONE },
+
+    { (FcChar8 *) "hintnone",      "hintstyle",   FC_HINT_NONE },
+    { (FcChar8 *) "hintslight",            "hintstyle",   FC_HINT_SLIGHT },
+    { (FcChar8 *) "hintmedium",            "hintstyle",   FC_HINT_MEDIUM },
+    { (FcChar8 *) "hintfull",      "hintstyle",   FC_HINT_FULL },
+
+    { (FcChar8 *) "antialias",     "antialias",    FcTrue },
+    { (FcChar8 *) "hinting",       "hinting",      FcTrue },
+    { (FcChar8 *) "verticallayout", "verticallayout",  FcTrue },
+    { (FcChar8 *) "autohint",      "autohint",     FcTrue },
+    { (FcChar8 *) "globaladvance",  "globaladvance",   FcTrue }, /* deprecated */
+    { (FcChar8 *) "outline",       "outline",      FcTrue },
+    { (FcChar8 *) "scalable",      "scalable",     FcTrue },
+    { (FcChar8 *) "minspace",      "minspace",     FcTrue },
+    { (FcChar8 *) "embolden",      "embolden",     FcTrue },
+    { (FcChar8 *) "embeddedbitmap", "embeddedbitmap",  FcTrue },
+    { (FcChar8 *) "decorative",            "decorative",   FcTrue },
+    { (FcChar8 *) "lcdnone",       "lcdfilter",    FC_LCD_NONE },
+    { (FcChar8 *) "lcddefault",            "lcdfilter",    FC_LCD_DEFAULT },
+    { (FcChar8 *) "lcdlight",      "lcdfilter",    FC_LCD_LIGHT },
+    { (FcChar8 *) "lcdlegacy",     "lcdfilter",    FC_LCD_LEGACY },
 };
 
 #define NUM_FC_CONSTANTS   (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])
 
-typedef struct _FcConstantList FcConstantList;
-
-struct _FcConstantList {
-    const FcConstantList    *next;
-    const FcConstant       *consts;
-    int                            nconsts;
-};
-
-static const FcConstantList _FcBaseConstantList = {
-    0,
-    _FcBaseConstants,
-    NUM_FC_CONSTANTS
-};
-
-static const FcConstantList    *_FcConstants = &_FcBaseConstantList;
-
 FcBool
 FcNameRegisterConstants (const FcConstant *consts, int nconsts)
 {
-    FcConstantList     *l;
-
-    l = (FcConstantList *) malloc (sizeof (FcConstantList));
-    if (!l)
-       return FcFalse;
-    l->consts = consts;
-    l->nconsts = nconsts;
-    l->next = _FcConstants;
-    _FcConstants = l;
-    return FcTrue;
+    /* Deprecated. */
+    return FcFalse;
 }
 
 FcBool
 FcNameUnregisterConstants (const FcConstant *consts, int nconsts)
 {
-    const FcConstantList       *l, **prev;
-
-    for (prev = &_FcConstants; 
-        (l = *prev); 
-        prev = (const FcConstantList **) &(l->next))
-    {
-       if (l->consts == consts && l->nconsts == nconsts)
-       {
-           *prev = l->next;
-           free ((void *) l);
-           return FcTrue;
-       }
-    }
+    /* Deprecated. */
     return FcFalse;
 }
 
 const FcConstant *
-FcNameGetConstant (FcChar8 *string)
+FcNameGetConstant (const FcChar8 *string)
 {
-    const FcConstantList    *l;
-    int                            i;
-    
-    for (l = _FcConstants; l; l = l->next)
-    {
-       for (i = 0; i < l->nconsts; i++)
-           if (!FcStrCmpIgnoreCase (string, l->consts[i].name))
-               return &l->consts[i];
-    }
+    unsigned int           i;
+
+    for (i = 0; i < NUM_FC_CONSTANTS; i++)
+       if (!FcStrCmpIgnoreCase (string, _FcBaseConstants[i].name))
+           return &_FcBaseConstants[i];
+
     return 0;
 }
 
 FcBool
-FcNameConstant (FcChar8 *string, int *result)
+FcNameConstant (const FcChar8 *string, int *result)
 {
     const FcConstant   *c;
 
@@ -230,13 +234,12 @@ FcNameConstant (FcChar8 *string, int *result)
 }
 
 FcBool
-FcNameBool (FcChar8 *v, FcBool *result)
+FcNameBool (const FcChar8 *v, FcBool *result)
 {
     char    c0, c1;
 
     c0 = *v;
-    if (isupper (c0))
-       c0 = tolower (c0);
+    c0 = FcToLower (c0);
     if (c0 == 't' || c0 == 'y' || c0 == '1')
     {
        *result = FcTrue;
@@ -250,8 +253,7 @@ FcNameBool (FcChar8 *v, FcBool *result)
     if (c0 == 'o')
     {
        c1 = v[1];
-       if (isupper (c1))
-           c1 = tolower (c1);
+       c1 = FcToLower (c1);
        if (c1 == 'n')
        {
            *result = FcTrue;
@@ -267,18 +269,21 @@ FcNameBool (FcChar8 *v, FcBool *result)
 }
 
 static FcValue
-FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m)
+FcNameConvert (FcType type, FcChar8 *string)
 {
     FcValue    v;
+    FcMatrix   m;
 
     v.type = type;
-    switch (v.type) {
+    switch ((int) v.type) {
     case FcTypeInteger:
        if (!FcNameConstant (string, &v.u.i))
            v.u.i = atoi ((char *) string);
        break;
     case FcTypeString:
-       v.u.s = string;
+       v.u.s = FcStrdup (string);
+       if (!v.u.s)
+           v.type = FcTypeVoid;
        break;
     case FcTypeBool:
        if (!FcNameBool (string, &v.u.b))
@@ -288,11 +293,19 @@ FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m)
        v.u.d = strtod ((char *) string, 0);
        break;
     case FcTypeMatrix:
-       v.u.m = m;
-       sscanf ((char *) string, "%lg %lg %lg %lg", &m->xx, &m->xy, &m->yx, &m->yy);
+       FcMatrixInit (&m);
+       sscanf ((char *) string, "%lg %lg %lg %lg", &m.xx, &m.xy, &m.yx, &m.yy);
+       v.u.m = FcMatrixCopy (&m);
        break;
     case FcTypeCharSet:
        v.u.c = FcNameParseCharSet (string);
+       if (!v.u.c)
+           v.type = FcTypeVoid;
+       break;
+    case FcTypeLangSet:
+       v.u.l = FcNameParseLangSet (string);
+       if (!v.u.l)
+           v.type = FcTypeVoid;
        break;
     default:
        break;
@@ -304,7 +317,13 @@ static const FcChar8 *
 FcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *last)
 {
     FcChar8    c;
-    
+
+    while ((c = *cur))
+    {
+       if (!isspace (c))
+           break;
+       ++cur;
+    }
     while ((c = *cur))
     {
        if (c == '\\')
@@ -334,10 +353,10 @@ FcNameParse (const FcChar8 *name)
     FcChar8            *e;
     FcChar8            delim;
     FcValue            v;
-    FcMatrix           m;
     const FcObjectType *t;
     const FcConstant   *c;
 
+    /* freed below */
     save = malloc (strlen ((char *) name) + 1);
     if (!save)
        goto bail0;
@@ -382,17 +401,15 @@ FcNameParse (const FcChar8 *name)
                for (;;)
                {
                    name = FcNameFindNext (name, ":,", save, &delim);
-                   if (save[0] && t)
+                   if (t)
                    {
-                       v = FcNameConvert (t->type, save, &m);
+                       v = FcNameConvert (t->type, save);
                        if (!FcPatternAdd (pat, t->object, v, FcTrue))
                        {
-                           if (v.type == FcTypeCharSet)
-                               FcCharSetDestroy ((FcCharSet *) v.u.c);
+                           FcValueDestroy (v);
                            goto bail2;
                        }
-                       if (v.type == FcTypeCharSet)
-                           FcCharSetDestroy ((FcCharSet *) v.u.c);
+                       FcValueDestroy (v);
                    }
                    if (delim != ',')
                        break;
@@ -402,8 +419,22 @@ FcNameParse (const FcChar8 *name)
            {
                if ((c = FcNameGetConstant (save)))
                {
-                   if (!FcPatternAddInteger (pat, c->object, c->value))
+                   t = FcNameGetObjectType ((char *) c->object);
+                   if (t == NULL)
                        goto bail2;
+                   switch ((int) t->type) {
+                   case FcTypeInteger:
+                   case FcTypeDouble:
+                       if (!FcPatternAddInteger (pat, c->object, c->value))
+                           goto bail2;
+                       break;
+                   case FcTypeBool:
+                       if (!FcPatternAddBool (pat, c->object, c->value))
+                           goto bail2;
+                       break;
+                   default:
+                       break;
+                   }
                }
            }
        }
@@ -420,7 +451,7 @@ bail0:
     return 0;
 }
 static FcBool
-FcNameUnparseString (FcStrBuf      *buf, 
+FcNameUnparseString (FcStrBuf      *buf,
                     const FcChar8  *string,
                     const FcChar8  *escape)
 {
@@ -438,14 +469,16 @@ FcNameUnparseString (FcStrBuf         *buf,
     return FcTrue;
 }
 
-static FcBool
+FcBool
 FcNameUnparseValue (FcStrBuf   *buf,
-                   FcValue     v,
+                   FcValue     *v0,
                    FcChar8     *escape)
 {
     FcChar8    temp[1024];
-    
+    FcValue v = FcValueCanonicalize(v0);
+
     switch (v.type) {
+    case FcTypeUnknown:
     case FcTypeVoid:
        return FcTrue;
     case FcTypeInteger:
@@ -459,27 +492,29 @@ FcNameUnparseValue (FcStrBuf      *buf,
     case FcTypeBool:
        return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0);
     case FcTypeMatrix:
-       sprintf ((char *) temp, "%g %g %g %g", 
+       sprintf ((char *) temp, "%g %g %g %g",
                 v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
        return FcNameUnparseString (buf, temp, 0);
     case FcTypeCharSet:
        return FcNameUnparseCharSet (buf, v.u.c);
+    case FcTypeLangSet:
+       return FcNameUnparseLangSet (buf, v.u.l);
     case FcTypeFTFace:
        return FcTrue;
     }
     return FcFalse;
 }
 
-static FcBool
+FcBool
 FcNameUnparseValueList (FcStrBuf       *buf,
-                       FcValueList     *v,
+                       FcValueListPtr  v,
                        FcChar8         *escape)
 {
     while (v)
     {
-       if (!FcNameUnparseValue (buf, v->value, escape))
+       if (!FcNameUnparseValue (buf, &v->value, escape))
            return FcFalse;
-       if ((v = v->next))
+       if ((v = FcValueListNext(v)) != NULL)
            if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
                return FcFalse;
     }
@@ -492,51 +527,53 @@ FcNameUnparseValueList (FcStrBuf  *buf,
 FcChar8 *
 FcNameUnparse (FcPattern *pat)
 {
+    return FcNameUnparseEscaped (pat, FcTrue);
+}
+
+FcChar8 *
+FcNameUnparseEscaped (FcPattern *pat, FcBool escape)
+{
     FcStrBuf               buf;
     FcChar8                buf_static[8192];
     int                            i;
     FcPatternElt           *e;
-    const FcObjectTypeList  *l;
-    const FcObjectType     *o;
 
     FcStrBufInit (&buf, buf_static, sizeof (buf_static));
-    e = FcPatternFindElt (pat, FC_FAMILY);
+    e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT);
     if (e)
     {
-       if (!FcNameUnparseValueList (&buf, e->values, (FcChar8 *) FC_ESCAPE_FIXED))
+        if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
            goto bail0;
     }
-    e = FcPatternFindElt (pat, FC_SIZE);
+    e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT);
     if (e)
     {
        if (!FcNameUnparseString (&buf, (FcChar8 *) "-", 0))
            goto bail0;
-       if (!FcNameUnparseValueList (&buf, e->values, (FcChar8 *) FC_ESCAPE_FIXED))
+       if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
            goto bail0;
     }
-    for (l = _FcObjectTypes; l; l = l->next)
+    for (i = 0; i < NUM_OBJECT_TYPES; i++)
     {
-       for (i = 0; i < l->ntypes; i++)
+       FcObject id = i + 1;
+       const FcObjectType          *o;
+       o = &FcObjects[i];
+       if (!strcmp (o->object, FC_FAMILY) ||
+           !strcmp (o->object, FC_SIZE))
+           continue;
+    
+       e = FcPatternObjectFindElt (pat, id);
+       if (e)
        {
-           o = &l->types[i];
-           if (!strcmp (o->object, FC_FAMILY) || 
-               !strcmp (o->object, FC_SIZE) ||
-               !strcmp (o->object, FC_FILE))
-               continue;
-           
-           e = FcPatternFindElt (pat, o->object);
-           if (e)
-           {
-               if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
-                   goto bail0;
-               if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, (FcChar8 *) FC_ESCAPE_VARIABLE))
-                   goto bail0;
-               if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
-                   goto bail0;
-               if (!FcNameUnparseValueList (&buf, e->values, 
-                                            (FcChar8 *) FC_ESCAPE_VARIABLE))
-                   goto bail0;
-           }
+           if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
+               goto bail0;
+           if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
+               goto bail0;
+           if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
+               goto bail0;
+           if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ?
+                                        (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
+               goto bail0;
        }
     }
     return FcStrBufDone (&buf);
@@ -544,3 +581,6 @@ bail0:
     FcStrBufDestroy (&buf);
     return 0;
 }
+#define __fcname__
+#include "fcaliastail.h"
+#undef __fcname__