trivial code optimization
[platform/upstream/fontconfig.git] / src / fcxml.c
index d31caf5..6a2af85 100644 (file)
@@ -62,12 +62,30 @@ FcExprDestroy (FcExpr *e);
 void
 FcTestDestroy (FcTest *test)
 {
-    if (test->next)
-       FcTestDestroy (test->next);
     FcExprDestroy (test->expr);
     free (test);
 }
 
+void
+FcRuleDestroy (FcRule *rule)
+{
+    FcRule *n = rule->next;
+
+    switch (rule->type) {
+    case FcRuleTest:
+       FcTestDestroy (rule->u.test);
+       break;
+    case FcRuleEdit:
+       FcEditDestroy (rule->u.edit);
+       break;
+    default:
+       break;
+    }
+    free (rule);
+    if (n)
+       FcRuleDestroy (n);
+}
+
 static FcExpr *
 FcExprCreateInteger (FcConfig *config, int i)
 {
@@ -99,7 +117,7 @@ FcExprCreateString (FcConfig *config, const FcChar8 *s)
     if (e)
     {
        e->op = FcOpString;
-       e->u.sval = FcSharedStr (s);
+       e->u.sval = FcStrdup (s);
     }
     return e;
 }
@@ -205,7 +223,7 @@ FcExprCreateConst (FcConfig *config, const FcChar8 *constant)
     if (e)
     {
        e->op = FcOpConst;
-       e->u.constant = FcSharedStr (constant);
+       e->u.constant = FcStrdup (constant);
     }
     return e;
 }
@@ -234,7 +252,7 @@ FcExprDestroy (FcExpr *e)
     case FcOpDouble:
        break;
     case FcOpString:
-       FcSharedStrFree (e->u.sval);
+       FcFree (e->u.sval);
        break;
     case FcOpMatrix:
        FcExprMatrixFree (e->u.mexpr);
@@ -252,7 +270,7 @@ FcExprDestroy (FcExpr *e)
     case FcOpField:
        break;
     case FcOpConst:
-       FcSharedStrFree (e->u.constant);
+       FcFree (e->u.constant);
        break;
     case FcOpAssign:
     case FcOpAssignReplace:
@@ -260,6 +278,8 @@ FcExprDestroy (FcExpr *e)
     case FcOpPrependFirst:
     case FcOpAppend:
     case FcOpAppendLast:
+    case FcOpDelete:
+    case FcOpDeleteAll:
        break;
     case FcOpOr:
     case FcOpAnd:
@@ -298,8 +318,6 @@ FcExprDestroy (FcExpr *e)
 void
 FcEditDestroy (FcEdit *e)
 {
-    if (e->next)
-       FcEditDestroy (e->next);
     if (e->expr)
        FcExprDestroy (e->expr);
     free (e);
@@ -594,6 +612,10 @@ FcTypecheckValue (FcConfigParse *parse, FcType value, FcType type)
            return;
        if (type == (FcType) -1)
            return;
+       /* It's perfectly fine to use user-define elements in expressions,
+        * so don't warn in that case. */
+       if (value == (FcType) -1)
+           return;
        FcConfigMessage (parse, FcSevereWarning, "saw %s, expected %s",
                         FcTypeName (value), FcTypeName (type));
     }
@@ -699,7 +721,7 @@ FcTestCreate (FcConfigParse *parse,
              FcMatchKind   kind,
              FcQual        qual,
              const FcChar8 *field,
-             FcOp          compare,
+             unsigned int  compare,
              FcExpr        *expr)
 {
     FcTest     *test = (FcTest *) malloc (sizeof (FcTest));
@@ -708,7 +730,6 @@ FcTestCreate (FcConfigParse *parse,
     {
        const FcObjectType      *o;
        
-       test->next = 0;
        test->kind = kind;
        test->qual = qual;
        test->object = FcObjectFromName ((const char *) field);
@@ -734,7 +755,6 @@ FcEditCreate (FcConfigParse *parse,
     {
        const FcObjectType      *o;
 
-       e->next = 0;
        e->object = object;
        e->op = op;
        e->expr = expr;
@@ -746,6 +766,34 @@ FcEditCreate (FcConfigParse        *parse,
     return e;
 }
 
+static FcRule *
+FcRuleCreate (FcRuleType type,
+             void       *p)
+{
+    FcRule *r = (FcRule *) malloc (sizeof (FcRule));
+
+    if (!r)
+       return NULL;
+
+    r->next = NULL;
+    r->type = type;
+    switch (type)
+    {
+    case FcRuleTest:
+       r->u.test = (FcTest *) p;
+       break;
+    case FcRuleEdit:
+       r->u.edit = (FcEdit *) p;
+       break;
+    default:
+       free (r);
+       r = NULL;
+       break;
+    }
+
+    return r;
+}
+
 static FcVStack *
 FcVStackCreateAndPush (FcConfigParse *parse)
 {
@@ -1088,10 +1136,26 @@ FcPStackPop (FcConfigParse *parse)
        FcConfigMessage (parse, FcSevereError, "mismatching element");
        return FcFalse;
     }
+
+    if (parse->pstack->attr)
+    {
+       /* Warn about unused attrs. */
+       FcChar8 **attrs = parse->pstack->attr;
+       while (*attrs)
+       {
+           if (attrs[0][0])
+           {
+               FcConfigMessage (parse, FcSevereError, "invalid attribute '%s'", attrs[0]);
+           }
+           attrs += 2;
+       }
+    }
+
     FcVStackClear (parse);
     old = parse->pstack;
     parse->pstack = old->prev;
     FcStrBufDestroy (&old->str);
+
     if (old->attr && old->attr != old->attr_buf_static)
        free (old->attr);
 
@@ -1103,7 +1167,7 @@ FcPStackPop (FcConfigParse *parse)
 }
 
 static FcBool
-FcConfigInit (FcConfigParse *parse, const FcChar8 *name, FcConfig *config, XML_Parser parser)
+FcConfigParseInit (FcConfigParse *parse, const FcChar8 *name, FcConfig *config, XML_Parser parser)
 {
     parse->pstack = 0;
     parse->pstack_static_used = 0;
@@ -1137,7 +1201,10 @@ FcConfigGetAttribute (FcConfigParse *parse, const char *attr)
     while (*attrs)
     {
        if (!strcmp ((char *) *attrs, attr))
+       {
+           attrs[0][0] = '\0'; /* Mark as used. */
            return attrs[1];
+       }
        attrs += 2;
     }
     return 0;
@@ -1396,7 +1463,7 @@ static void
 FcParseRange (FcConfigParse *parse)
 {
     FcVStack   *vstack;
-    FcRange    r;
+    FcRange    r = {0, 0};
     FcChar32   n;
     int                count = 1;
 
@@ -1632,9 +1699,9 @@ static void
 FcParseAlias (FcConfigParse *parse)
 {
     FcExpr     *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0;
-    FcEdit     *edit = 0, *next;
+    FcEdit     *edit = 0;
     FcVStack   *vstack;
-    FcTest     *test = NULL;
+    FcRule     *rule = NULL, *r;
     FcValueBinding  binding;
 
     if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding))
@@ -1679,8 +1746,14 @@ FcParseAlias (FcConfigParse *parse)
            vstack->tag = FcVStackNone;
            break;
        case FcVStackTest:
-           vstack->u.test->next = test;
-           test = vstack->u.test;
+           if (rule)
+           {
+               r = FcRuleCreate (FcRuleTest, vstack->u.test);
+               r->next = rule;
+               rule = r;
+           }
+           else
+               rule = FcRuleCreate (FcRuleTest, vstack->u.test);
            vstack->tag = FcVStackNone;
            break;
        default:
@@ -1698,8 +1771,35 @@ FcParseAlias (FcConfigParse *parse)
            FcExprDestroy (accept);
        if (def)
            FcExprDestroy (def);
+       if (rule)
+           FcRuleDestroy (rule);
+       return;
+    }
+    if (!prefer &&
+       !accept &&
+       !def)
+    {
+       FcExprDestroy (family);
        return;
     }
+    else
+    {
+       FcTest *t = FcTestCreate (parse, FcMatchPattern,
+                                 FcQualAny,
+                                 (FcChar8 *) FC_FAMILY,
+                                 FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks),
+                                 family);
+       if (rule)
+       {
+           for (r = rule; r->next; r = r->next);
+           r->next = FcRuleCreate (FcRuleTest, t);
+           r = r->next;
+       }
+       else
+       {
+           r = rule = FcRuleCreate (FcRuleTest, t);
+       }
+    }
     if (prefer)
     {
        edit = FcEditCreate (parse,
@@ -1707,60 +1807,46 @@ FcParseAlias (FcConfigParse *parse)
                             FcOpPrepend,
                             prefer,
                             binding);
-       if (edit)
-           edit->next = 0;
-       else
+       if (!edit)
            FcExprDestroy (prefer);
+       else
+       {
+           r->next = FcRuleCreate (FcRuleEdit, edit);
+           r = r->next;
+       }
     }
     if (accept)
     {
-       next = edit;
        edit = FcEditCreate (parse,
                             FC_FAMILY_OBJECT,
                             FcOpAppend,
                             accept,
                             binding);
-       if (edit)
-           edit->next = next;
-       else
+       if (!edit)
            FcExprDestroy (accept);
+       else
+       {
+           r->next = FcRuleCreate (FcRuleEdit, edit);
+           r = r->next;
+       }
     }
     if (def)
     {
-       next = edit;
        edit = FcEditCreate (parse,
                             FC_FAMILY_OBJECT,
                             FcOpAppendLast,
                             def,
                             binding);
-       if (edit)
-           edit->next = next;
-       else
+       if (!edit)
            FcExprDestroy (def);
-    }
-    if (edit)
-    {
-       FcTest *t = FcTestCreate (parse, FcMatchPattern,
-                                 FcQualAny,
-                                 (FcChar8 *) FC_FAMILY,
-                                 FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks),
-                                 family);
-       if (test)
+       else
        {
-           FcTest *p = test;
-
-           while (p->next)
-               p = p->next;
-           p->next = t;
+           r->next = FcRuleCreate (FcRuleEdit, edit);
+           r = r->next;
        }
-       else
-           test = t;
-       if (test)
-           if (!FcConfigAddEdit (parse->config, test, edit, FcMatchPattern))
-               FcTestDestroy (test);
     }
-    else
-       FcExprDestroy (family);
+    if (!FcConfigAddRule (parse->config, rule, FcMatchPattern))
+       FcRuleDestroy (rule);
 }
 
 static FcExpr *
@@ -1938,7 +2024,7 @@ FcParseDir (FcConfigParse *parse)
 #ifdef _WIN32
     if (strcmp ((const char *) data, "CUSTOMFONTDIR") == 0)
     {
-       char *p;
+       FcChar8 *p;
        data = buffer;
        if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20))
        {
@@ -1953,11 +2039,11 @@ FcParseDir (FcConfigParse *parse)
         */
        p = _mbsrchr (data, '\\');
        if (p) *p = '\0';
-       strcat (data, "\\fonts");
+       strcat ((char *) data, "\\fonts");
     }
     else if (strcmp ((const char *) data, "APPSHAREFONTDIR") == 0)
     {
-       char *p;
+       FcChar8 *p;
        data = buffer;
        if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20))
        {
@@ -1966,7 +2052,7 @@ FcParseDir (FcConfigParse *parse)
        }
        p = _mbsrchr (data, '\\');
        if (p) *p = '\0';
-       strcat (data, "\\..\\share\\fonts");
+       strcat ((char *) data, "\\..\\share\\fonts");
     }
     else if (strcmp ((const char *) data, "WINDOWSFONTDIR") == 0)
     {
@@ -1979,8 +2065,8 @@ FcParseDir (FcConfigParse *parse)
            goto bail;
        }
        if (data [strlen ((const char *) data) - 1] != '\\')
-           strcat (data, "\\");
-       strcat (data, "fonts");
+           strcat ((char *) data, "\\");
+       strcat ((char *) data, "fonts");
     }
 #endif
     if (strlen ((char *) data) == 0)
@@ -2049,8 +2135,8 @@ FcParseCacheDir (FcConfigParse *parse)
            goto bail;
        }
        if (data [strlen ((const char *) data) - 1] != '\\')
-           strcat (data, "\\");
-       strcat (data, "fontconfig\\cache");
+           strcat ((char *) data, "\\");
+       strcat ((char *) data, "fontconfig\\cache");
     }
     else if (strcmp ((const char *) data, "LOCAL_APPDATA_FONTCONFIG_CACHE") == 0)
     {
@@ -2298,6 +2384,8 @@ static const FcOpMap fcModeOps[] = {
     { "prepend_first", FcOpPrependFirst    },
     { "append",                FcOpAppend          },
     { "append_last",   FcOpAppendLast      },
+    { "delete",                FcOpDelete          },
+    { "delete_all",    FcOpDeleteAll       },
 };
 
 #define NUM_MODE_OPS (int) (sizeof fcModeOps / sizeof fcModeOps[0])
@@ -2340,6 +2428,13 @@ FcParseEdit (FcConfigParse *parse)
        return;
 
     expr = FcPopBinary (parse, FcOpComma);
+    if ((mode == FcOpDelete || mode == FcOpDeleteAll) &&
+       expr != NULL)
+    {
+       FcConfigMessage (parse, FcSevereWarning, "Expression doesn't take any effects for delete and delete_all");
+       FcExprDestroy (expr);
+       expr = NULL;
+    }
     edit = FcEditCreate (parse, FcObjectFromName ((char *) name),
                         mode, expr, binding);
     if (!edit)
@@ -2357,9 +2452,9 @@ FcParseMatch (FcConfigParse *parse)
 {
     const FcChar8   *kind_name;
     FcMatchKind            kind;
-    FcTest         *test = 0;
     FcEdit         *edit = 0;
     FcVStack       *vstack;
+    FcRule         *rule = NULL, *r;
 
     kind_name = FcConfigGetAttribute (parse, "target");
     if (!kind_name)
@@ -2382,20 +2477,25 @@ FcParseMatch (FcConfigParse *parse)
     {
        switch ((int) vstack->tag) {
        case FcVStackTest:
-           vstack->u.test->next = test;
-           test = vstack->u.test;
+           r = FcRuleCreate (FcRuleTest, vstack->u.test);
+           if (rule)
+               r->next = rule;
+           rule = r;
            vstack->tag = FcVStackNone;
            break;
        case FcVStackEdit:
-           vstack->u.edit->next = edit;
-           edit = vstack->u.edit;
-           vstack->tag = FcVStackNone;
-           if (kind == FcMatchScan && edit->object > FC_MAX_BASE_OBJECT)
+           if (kind == FcMatchScan && vstack->u.edit->object > FC_MAX_BASE_OBJECT)
            {
                FcConfigMessage (parse, FcSevereError,
                                 "<match target=\"scan\"> cannot edit user-defined object \"%s\"",
                                 FcObjectName(edit->object));
+               break;
            }
+           r = FcRuleCreate (FcRuleEdit, vstack->u.edit);
+           if (rule)
+               r->next = rule;
+           rule = r;
+           vstack->tag = FcVStackNone;
            break;
        default:
            FcConfigMessage (parse, FcSevereWarning, "invalid match element");
@@ -2403,7 +2503,7 @@ FcParseMatch (FcConfigParse *parse)
        }
        FcVStackPopAndDestroy (parse);
     }
-    if (!FcConfigAddEdit (parse->config, test, edit, kind))
+    if (!FcConfigAddRule (parse->config, rule, kind))
        FcConfigMessage (parse, FcSevereError, "out of memory");
 }
 
@@ -2455,7 +2555,7 @@ FcPopValue (FcConfigParse *parse)
 
     switch ((int) vstack->tag) {
     case FcVStackString:
-       value.u.s = FcSharedStr (vstack->u.string);
+       value.u.s = FcStrdup (vstack->u.string);
        if (value.u.s)
            value.type = FcTypeString;
        break;
@@ -2956,7 +3056,7 @@ FcConfigParseAndLoad (FcConfig        *config,
     if (FcDebug () & FC_DBG_CONFIG)
        printf ("\tLoading config file %s\n", filename);
 
-    fd = open ((char *) filename, O_RDONLY);
+    fd = FcOpen ((char *) filename, O_RDONLY);
     if (fd == -1) {
        FcStrFree (filename);
        goto bail0;
@@ -2980,7 +3080,7 @@ FcConfigParseAndLoad (FcConfig        *config,
     if (!p)
        goto bail1;
 
-    if (!FcConfigInit (&parse, name, config, p))
+    if (!FcConfigParseInit (&parse, name, config, p))
        goto bail2;
 
 #ifndef ENABLE_LIBXML2