Commit c357a11aa690533620790f3df959508074cbd7e1

Ran Benita 2012-03-01T21:20:45

Add function to free XkbFile's Signed-off-by: Ran Benita <ran234@gmail.com>

diff --git a/src/xkbcomp/parseutils.c b/src/xkbcomp/parseutils.c
index bc56c78..158dc13 100644
--- a/src/xkbcomp/parseutils.c
+++ b/src/xkbcomp/parseutils.c
@@ -27,6 +27,7 @@
 #include "parseutils.h"
 #include "xkbmisc.h"
 #include "xkbpath.h"
+#include "xkbparse.h"
 #include <X11/keysym.h>
 #include <X11/Xalloca.h>
 
@@ -792,3 +793,182 @@ StmtSetMerge(ParseCommon * stmt, unsigned merge)
     }
     return merge;
 }
+
+static void
+FreeStmt(ParseCommon *stmt);
+
+static void
+FreeExpr(ExprDef *expr)
+{
+    int i;
+
+    if (!expr)
+        return;
+
+    switch (expr->op)
+    {
+    case ExprActionList:
+    case OpNegate:
+    case OpUnaryPlus:
+    case OpNot:
+    case OpInvert:
+        FreeStmt(&expr->value.child->common);
+        break;
+    case OpDivide:
+    case OpAdd:
+    case OpSubtract:
+    case OpMultiply:
+    case OpAssign:
+        FreeStmt(&expr->value.binary.left->common);
+        FreeStmt(&expr->value.binary.right->common);
+        break;
+    case ExprActionDecl:
+        FreeStmt(&expr->value.action.args->common);
+        break;
+    case ExprArrayRef:
+        FreeStmt(&expr->value.array.entry->common);
+        break;
+    case ExprKeysymList:
+        for (i = 0; i < expr->value.list.nSyms; i++)
+            free(expr->value.list.syms[i]);
+        free(expr->value.list.syms);
+        break;
+    default:
+        break;
+    }
+}
+
+static void
+FreeInclude(IncludeStmt *incl)
+{
+    IncludeStmt *next;
+
+    while (incl)
+    {
+        next = incl->next;
+
+        free(incl->file);
+        free(incl->map);
+        free(incl->modifier);
+        free(incl->path);
+        free(incl->stmt);
+
+        free(incl);
+        incl = next;
+    }
+}
+
+static void
+FreeStmt(ParseCommon *stmt)
+{
+    ParseCommon *next;
+    YYSTYPE u;
+
+    while (stmt)
+    {
+        next = stmt->next;
+        u.any = stmt;
+
+        switch (stmt->stmtType)
+        {
+        case StmtInclude:
+            FreeInclude((IncludeStmt *)stmt);
+            stmt = NULL;
+            break;
+        case StmtExpr:
+            FreeExpr(u.expr);
+            break;
+        case StmtVarDef:
+            FreeStmt(&u.var->name->common);
+            FreeStmt(&u.var->value->common);
+            break;
+        case StmtKeyTypeDef:
+            FreeStmt(&u.keyType->body->common);
+            break;
+        case StmtInterpDef:
+            free(u.interp->sym);
+            FreeStmt(&u.interp->match->common);
+            FreeStmt(&u.interp->def->common);
+            break;
+        case StmtVModDef:
+            FreeStmt(&u.vmod->value->common);
+            break;
+        case StmtSymbolsDef:
+            FreeStmt(&u.syms->symbols->common);
+            break;
+        case StmtModMapDef:
+            FreeStmt(&u.modMask->keys->common);
+            break;
+        case StmtGroupCompatDef:
+            FreeStmt(&u.groupCompat->def->common);
+            break;
+        case StmtIndicatorMapDef:
+            FreeStmt(&u.ledMap->body->common);
+            break;
+        case StmtIndicatorNameDef:
+            FreeStmt(&u.ledName->name->common);
+            break;
+        case StmtOutlineDef:
+            FreeStmt(&u.outline->points->common);
+            break;
+        case StmtShapeDef:
+            FreeStmt(&u.shape->outlines->common);
+            break;
+        case StmtKeyDef:
+            free(u.key->name);
+            FreeStmt(&u.key->expr->common);
+            break;
+        case StmtRowDef:
+            FreeStmt(&u.row->keys->common);
+            break;
+        case StmtSectionDef:
+            FreeStmt(&u.section->rows->common);
+            break;
+        case StmtOverlayKeyDef:
+            break;
+        case StmtOverlayDef:
+            FreeStmt(&u.overlay->keys->common);
+            break;
+        case StmtDoodadDef:
+            FreeStmt(&u.doodad->body->common);
+            break;
+        default:
+            break;
+        }
+
+        free(stmt);
+        stmt = next;
+    }
+}
+
+void
+FreeXKBFile(XkbFile *file)
+{
+    XkbFile *next;
+
+    while (file)
+    {
+        next = (XkbFile *)file->common.next;
+
+        switch (file->type)
+        {
+        case XkmKeymapFile:
+        case XkmSemanticsFile:
+        case XkmLayoutFile:
+            FreeXKBFile((XkbFile *)file->defs);
+            break;
+        case XkmTypesIndex:
+        case XkmCompatMapIndex:
+        case XkmSymbolsIndex:
+        case XkmKeyNamesIndex:
+        case XkmGeometryIndex:
+            FreeStmt(file->defs);
+            break;
+        }
+
+        free(file->name);
+        /* free(file->topName); */
+        free(file);
+        file = next;
+    }
+}
diff --git a/src/xkbcomp/parseutils.h b/src/xkbcomp/parseutils.h
index 00d198c..0733455 100644
--- a/src/xkbcomp/parseutils.h
+++ b/src/xkbcomp/parseutils.h
@@ -177,6 +177,8 @@ extern XkbFile *CreateXKBFile(int /* type */ ,
                               unsigned  /* flags */
     );
 
+extern void FreeXKBFile(XkbFile *file);
+
 extern void yyerror(const char *        /* msg */
     );