]> git.wh0rd.org - fontconfig.git/blobdiff - src/fcxml.c
[fcxml] Don't allocate attr array if there are no attributes
[fontconfig.git] / src / fcxml.c
index 5b7e19118fefb79bb8fb45fa905f8fd4dbbe2bb3..ccc9c194d4463e6803de95f088a99dfe38a41ec1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $RCSId: xc/lib/fontconfig/src/fcxml.c,v 1.21 2002/08/22 18:53:22 keithp Exp $
+ * fontconfig/src/fcxml.c
  *
  * Copyright © 2002 Keith Packard
  *
@@ -450,7 +450,7 @@ typedef struct _FcVStack {
        int             integer;
        double          _double;
        FcMatrix        *matrix;
-       FcBool          bool;
+       FcBool          bool_;
 
        FcTest          *test;
        FcQual          qual;
@@ -545,6 +545,8 @@ FcTypecheckValue (FcConfigParse *parse, FcType value, FcType type)
        if ((value == FcTypeLangSet && type == FcTypeString) ||
            (value == FcTypeString && type == FcTypeLangSet))
            return;
+       if (type == (FcType) -1)
+           return;
        FcConfigMessage (parse, FcSevereWarning, "saw %s, expected %s",
                         FcTypeName (value), FcTypeName (type));
     }
@@ -556,6 +558,10 @@ FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type)
     const FcObjectType *o;
     const FcConstant   *c;
     
+    /* If parsing the expression failed, some nodes may be NULL */
+    if (!expr)
+       return;
+
     switch (expr->op) {
     case FcOpInteger:
     case FcOpDouble:
@@ -815,12 +821,12 @@ FcVStackPushMatrix (FcConfigParse *parse, FcMatrix *matrix)
 }
 
 static FcBool
-FcVStackPushBool (FcConfigParse *parse, FcBool bool)
+FcVStackPushBool (FcConfigParse *parse, FcBool bool_)
 {
     FcVStack    *vstack = FcVStackCreate ();
     if (!vstack)
        return FcFalse;
-    vstack->u.bool = bool;
+    vstack->u.bool_ = bool_;
     vstack->tag = FcVStackBool;
     FcVStackPush (parse, vstack);
     return FcTrue;
@@ -933,9 +939,14 @@ FcConfigSaveAttr (const XML_Char **attr)
     slen = 0;
     for (i = 0; attr[i]; i++)
        slen += strlen ((char *) attr[i]) + 1;
+    if (i == 0)
+       return 0;
     new = malloc ((i + 1) * sizeof (FcChar8 *) + slen);
     if (!new)
+    {
+       FcConfigMessage (0, FcSevereError, "out of memory");
        return 0;
+    }
     FcMemAlloc (FC_MEM_ATTR, 1);    /* size is too expensive */
     s = (FcChar8 *) (new + (i + 1));
     for (i = 0; attr[i]; i++)
@@ -958,14 +969,7 @@ FcPStackPush (FcConfigParse *parse, FcElement element, const XML_Char **attr)
     FcMemAlloc (FC_MEM_PSTACK, sizeof (FcPStack));
     new->prev = parse->pstack;
     new->element = element;
-    if (attr)
-    {
-       new->attr = FcConfigSaveAttr (attr);
-       if (!new->attr)
-           FcConfigMessage (parse, FcSevereError, "out of memory");
-    }
-    else
-       new->attr = 0;
+    new->attr = FcConfigSaveAttr (attr);
     FcStrBufInit (&new->str, 0, 0);
     parse->pstack = new;
     return FcTrue;
@@ -1103,7 +1107,7 @@ FcParseInt (FcConfigParse *parse)
     
     if (!parse->pstack)
        return;
-    s = FcStrBufDone (&parse->pstack->str);
+    s = FcStrBufDoneStatic (&parse->pstack->str);
     if (!s)
     {
        FcConfigMessage (parse, FcSevereError, "out of memory");
@@ -1115,7 +1119,7 @@ FcParseInt (FcConfigParse *parse)
        FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid integer", s);
     else
        FcVStackPushInteger (parse, l);
-    FcStrFree (s);
+    FcStrBufDestroy (&parse->pstack->str);
 }
 
 /*
@@ -1184,7 +1188,7 @@ FcParseDouble (FcConfigParse *parse)
     
     if (!parse->pstack)
        return;
-    s = FcStrBufDone (&parse->pstack->str);
+    s = FcStrBufDoneStatic (&parse->pstack->str);
     if (!s)
     {
        FcConfigMessage (parse, FcSevereError, "out of memory");
@@ -1196,7 +1200,7 @@ FcParseDouble (FcConfigParse *parse)
        FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid double", s);
     else
        FcVStackPushDouble (parse, d);
-    FcStrFree (s);
+    FcStrBufDestroy (&parse->pstack->str);
 }
 
 static void
@@ -1255,13 +1259,13 @@ FcParseMatrix (FcConfigParse *parse)
 }
 
 static FcBool
-FcConfigLexBool (FcConfigParse *parse, const FcChar8 *bool)
+FcConfigLexBool (FcConfigParse *parse, const FcChar8 *bool_)
 {
     FcBool  result = FcFalse;
 
-    if (!FcNameBool (bool, &result))
+    if (!FcNameBool (bool_, &result))
        FcConfigMessage (parse, FcSevereWarning, "\"%s\" is not known boolean",
-                        bool);
+                        bool_);
     return result;
 }
 
@@ -1272,14 +1276,41 @@ FcParseBool (FcConfigParse *parse)
 
     if (!parse->pstack)
        return;
-    s = FcStrBufDone (&parse->pstack->str);
+    s = FcStrBufDoneStatic (&parse->pstack->str);
     if (!s)
     {
        FcConfigMessage (parse, FcSevereError, "out of memory");
        return;
     }
     FcVStackPushBool (parse, FcConfigLexBool (parse, s));
-    FcStrFree (s);
+    FcStrBufDestroy (&parse->pstack->str);
+}
+
+static FcBool
+FcConfigLexBinding (FcConfigParse   *parse,
+                   const FcChar8   *binding_string,
+                   FcValueBinding  *binding_ret)
+{
+    FcValueBinding binding;
+    
+    if (!binding_string)
+       binding = FcValueBindingWeak;
+    else
+    {
+       if (!strcmp ((char *) binding_string, "weak"))
+           binding = FcValueBindingWeak;
+       else if (!strcmp ((char *) binding_string, "strong"))
+           binding = FcValueBindingStrong;
+       else if (!strcmp ((char *) binding_string, "same"))
+           binding = FcValueBindingSame;
+       else
+       {
+           FcConfigMessage (parse, FcSevereWarning, "invalid binding \"%s\"", binding_string);
+           return FcFalse;
+       }
+    }
+    *binding_ret = binding;
+    return FcTrue;
 }
 
 static void
@@ -1332,14 +1363,14 @@ FcParseFamily (FcConfigParse *parse)
 
     if (!parse->pstack)
        return;
-    s = FcStrBufDone (&parse->pstack->str);
+    s = FcStrBufDoneStatic (&parse->pstack->str);
     if (!s)
     {
        FcConfigMessage (parse, FcSevereError, "out of memory");
        return;
     }
     expr = FcExprCreateString (s);
-    FcStrFree (s);
+    FcStrBufDestroy (&parse->pstack->str);
     if (expr)
        FcVStackPushExpr (parse, FcVStackFamily, expr);
 }
@@ -1351,7 +1382,10 @@ FcParseAlias (FcConfigParse *parse)
     FcEdit     *edit = 0, *next;
     FcVStack   *vstack;
     FcTest     *test;
+    FcValueBinding  binding;
 
+    if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding))
+       return;
     while ((vstack = FcVStackPop (parse))) 
     {
        switch (vstack->tag) {
@@ -1413,7 +1447,7 @@ FcParseAlias (FcConfigParse *parse)
                             FC_FAMILY_OBJECT,
                             FcOpPrepend,
                             prefer,
-                            FcValueBindingWeak);
+                            binding);
        if (edit)
            edit->next = 0;
        else
@@ -1426,7 +1460,7 @@ FcParseAlias (FcConfigParse *parse)
                             FC_FAMILY_OBJECT,
                             FcOpAppend,
                             accept,
-                            FcValueBindingWeak);
+                            binding);
        if (edit)
            edit->next = next;
        else
@@ -1439,7 +1473,7 @@ FcParseAlias (FcConfigParse *parse)
                             FC_FAMILY_OBJECT,
                             FcOpAppendLast,
                             def,
-                            FcValueBindingWeak);
+                            binding);
        if (edit)
            edit->next = next;
        else
@@ -1499,7 +1533,7 @@ FcPopExpr (FcConfigParse *parse)
        expr = FcExprCreateMatrix (vstack->u.matrix);
        break;
     case FcVStackBool:
-       expr = FcExprCreateBool (vstack->u.bool);
+       expr = FcExprCreateBool (vstack->u.bool_);
        break;
     case FcVStackTest:
        break;
@@ -1595,7 +1629,7 @@ FcParseInclude (FcConfigParse *parse)
     const FcChar8   *i;
     FcBool         ignore_missing = FcFalse;
     
-    s = FcStrBufDone (&parse->pstack->str);
+    s = FcStrBufDoneStatic (&parse->pstack->str);
     if (!s)
     {
        FcConfigMessage (parse, FcSevereError, "out of memory");
@@ -1606,7 +1640,7 @@ FcParseInclude (FcConfigParse *parse)
        ignore_missing = FcTrue;
     if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing))
        parse->error = FcTrue;
-    FcStrFree (s);
+    FcStrBufDestroy (&parse->pstack->str);
 }
 
 typedef struct _FcOpMap {
@@ -1644,7 +1678,6 @@ FcConfigLexCompare (const FcChar8 *compare)
     return FcConfigLexOp (compare, fcCompareOps, NUM_COMPARE_OPS);
 }
 
-
 static void
 FcParseTest (FcConfigParse *parse)
 {
@@ -1667,6 +1700,8 @@ FcParseTest (FcConfigParse *parse)
            kind = FcMatchPattern;
        else if (!strcmp ((char *) kind_string, "font"))
            kind = FcMatchFont;
+       else if (!strcmp ((char *) kind_string, "scan"))
+           kind = FcMatchScan;
        else if (!strcmp ((char *) kind_string, "default"))
            kind = FcMatchDefault;
        else
@@ -1749,7 +1784,6 @@ FcParseEdit (FcConfigParse *parse)
 {
     const FcChar8   *name;
     const FcChar8   *mode_string;
-    const FcChar8   *binding_string;
     FcOp           mode;
     FcValueBinding  binding;
     FcExpr         *expr;
@@ -1773,23 +1807,9 @@ FcParseEdit (FcConfigParse *parse)
            return;
        }
     }
-    binding_string = FcConfigGetAttribute (parse, "binding");
-    if (!binding_string)
-       binding = FcValueBindingWeak;
-    else
-    {
-       if (!strcmp ((char *) binding_string, "weak"))
-           binding = FcValueBindingWeak;
-       else if (!strcmp ((char *) binding_string, "strong"))
-           binding = FcValueBindingStrong;
-       else if (!strcmp ((char *) binding_string, "same"))
-           binding = FcValueBindingSame;
-       else
-       {
-           FcConfigMessage (parse, FcSevereWarning, "invalid edit binding \"%s\"", binding_string);
-           return;
-       }
-    }
+    if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding))
+       return;
+
     expr = FcPopBinary (parse, FcOpComma);
     edit = FcEditCreate (parse, FcObjectFromName ((char *) name),
                         mode, expr, binding);
@@ -1821,6 +1841,8 @@ FcParseMatch (FcConfigParse *parse)
            kind = FcMatchPattern;
        else if (!strcmp ((char *) kind_name, "font"))
            kind = FcMatchFont;
+       else if (!strcmp ((char *) kind_name, "scan"))
+           kind = FcMatchScan;
        else
        {
            FcConfigMessage (parse, FcSevereWarning, "invalid match target \"%s\"", kind_name);
@@ -1839,6 +1861,12 @@ FcParseMatch (FcConfigParse *parse)
            vstack->u.edit->next = edit;
            edit = vstack->u.edit;
            vstack->tag = FcVStackNone;
+           if (kind == FcMatchScan && edit->object > FC_MAX_BASE_OBJECT)
+           {
+               FcConfigMessage (parse, FcSevereError, 
+                                "<match target=\"scan\"> cannot edit user-defined object \"%s\"",
+                                FcObjectName(edit->object));
+           }
            break;
        default:
            FcConfigMessage (parse, FcSevereWarning, "invalid match element");
@@ -1920,7 +1948,7 @@ FcPopValue (FcConfigParse *parse)
            value.type = FcTypeMatrix;
        break;
     case FcVStackBool:
-       value.u.b = vstack->u.bool;
+       value.u.b = vstack->u.bool_;
        value.type = FcTypeBool;
        break;
     default:
@@ -1962,8 +1990,10 @@ FcParsePatelt (FcConfigParse *parse)
        if (!FcPatternAdd (pattern, name, value, FcTrue))
        {
            FcConfigMessage (parse, FcSevereError, "out of memory");
+            FcValueDestroy(value);
            break;
        }
+        FcValueDestroy(value);
     }
 
     FcVStackPushPattern (parse, pattern);
@@ -2016,14 +2046,56 @@ FcEndElement(void *userData, const XML_Char *name)
     case FcElementFontconfig:
        break;
     case FcElementDir:
-       data = FcStrBufDone (&parse->pstack->str);
+       data = FcStrBufDoneStatic (&parse->pstack->str);
        if (!data)
        {
            FcConfigMessage (parse, FcSevereError, "out of memory");
            break;
        }
 #ifdef _WIN32
-       if (strcmp (data, "WINDOWSFONTDIR") == 0)
+       if (strcmp (data, "CUSTOMFONTDIR") == 0)
+       {
+               char *p;
+               FcStrFree (data);
+               data = malloc (1000);
+               if (!data)
+               {
+                       FcConfigMessage (parse, FcSevereError, "out of memory");
+                       break;
+               }
+               FcMemAlloc (FC_MEM_STRING, 1000);
+               if(!GetModuleFileName(NULL, data, 1000))
+               {
+                       FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
+                       FcStrFree (data);
+                       break;
+               }
+               p = strrchr (data, '\\');
+               if (p) *p = '\0';
+               strcat (data, "\\fonts");
+       }
+       else if (strcmp (data, "APPSHAREFONTDIR") == 0)
+       {
+               char *p;
+               FcStrFree (data);
+               data = malloc (1000);
+               if (!data)
+               {
+                       FcConfigMessage (parse, FcSevereError, "out of memory");
+                       break;
+               }
+               FcMemAlloc (FC_MEM_STRING, 1000);
+               if(!GetModuleFileName(NULL, data, 1000))
+               {
+                       FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
+                       FcStrFree (data);
+                       break;
+               }
+               p = strrchr (data, '\\');
+               if (p) *p = '\0';
+               strcat (data, "\\..\\share\\fonts");
+       }
+       else if (strcmp (data, "WINDOWSFONTDIR") == 0)
        {
            int rc;
            FcStrFree (data);
@@ -2046,12 +2118,14 @@ FcEndElement(void *userData, const XML_Char *name)
            strcat (data, "fonts");
        }
 #endif
-       if (!FcStrUsesHome (data) || FcConfigHome ())
+       if (strlen ((char *) data) == 0)
+           FcConfigMessage (parse, FcSevereWarning, "empty font directory name ignored");
+       else if (!FcStrUsesHome (data) || FcConfigHome ())
        {
            if (!FcConfigAddDir (parse->config, data))
                FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", data);
        }
-       FcStrFree (data);
+       FcStrBufDestroy (&parse->pstack->str);
        break;
     case FcElementCacheDir:
        data = FcStrBufDone (&parse->pstack->str);
@@ -2060,6 +2134,30 @@ FcEndElement(void *userData, const XML_Char *name)
            FcConfigMessage (parse, FcSevereError, "out of memory");
            break;
        }
+#ifdef _WIN32
+       if (strcmp (data, "WINDOWSTEMPDIR_FONTCONFIG_CACHE") == 0)
+       {
+           int rc;
+           FcStrFree (data);
+           data = malloc (1000);
+           if (!data)
+           {
+               FcConfigMessage (parse, FcSevereError, "out of memory");
+               break;
+           }
+           FcMemAlloc (FC_MEM_STRING, 1000);
+           rc = GetTempPath (800, data);
+           if (rc == 0 || rc > 800)
+           {
+               FcConfigMessage (parse, FcSevereError, "GetWindowsDirectory failed");
+               FcStrFree (data);
+               break;
+           }
+           if (data [strlen (data) - 1] != '\\')
+               strcat (data, "\\");
+           strcat (data, "fontconfig\\cache");
+       }
+#endif
        if (!FcStrUsesHome (data) || FcConfigHome ())
        {
            if (!FcConfigAddCacheDir (parse->config, data))
@@ -2069,14 +2167,14 @@ FcEndElement(void *userData, const XML_Char *name)
        break;
        
     case FcElementCache:
-       data = FcStrBufDone (&parse->pstack->str);
+       data = FcStrBufDoneStatic (&parse->pstack->str);
        if (!data)
        {
            FcConfigMessage (parse, FcSevereError, "out of memory");
            break;
        }
        /* discard this data; no longer used */
-       FcStrFree (data);
+       FcStrBufDestroy (&parse->pstack->str);
        break;
     case FcElementInclude:
        FcParseInclude (parse);
@@ -2275,6 +2373,14 @@ FcEndDoctypeDecl (void *userData)
 
 #endif /* ENABLE_LIBXML2 */
 
+static int
+FcSortCmpStr (const void *a, const void *b)
+{
+    const FcChar8    *as = *((FcChar8 **) a);
+    const FcChar8    *bs = *((FcChar8 **) b);
+    return FcStrCmp (as, bs);
+}
+
 static FcBool
 FcConfigParseAndLoadDir (FcConfig      *config,
                         const FcChar8  *name,
@@ -2344,7 +2450,7 @@ FcConfigParseAndLoadDir (FcConfig *config,
     {
        int i;
        qsort (files->strs, files->num, sizeof (FcChar8 *), 
-              (int (*)(const void *, const void *)) FcStrCmp);
+              (int (*)(const void *, const void *)) FcSortCmpStr);
        for (i = 0; ret && i < files->num; i++)
            ret = FcConfigParseAndLoad (config, files->strs[i], complain);
     }
@@ -2487,3 +2593,6 @@ bail0:
     }
     return FcTrue;
 }
+#define __fcxml__
+#include "fcaliastail.h"
+#undef __fcxml__