a2c67a04cef483baf7a7281004ae88684a53a711
kent
  Wed Apr 3 19:54:59 2013 -0700
Tidying up some of the meta code.  Ref #10536
diff --git src/lib/meta.c src/lib/meta.c
index 70e4c18..c1ad25e 100644
--- src/lib/meta.c
+++ src/lib/meta.c
@@ -17,38 +17,100 @@
 #include "hash.h"
 #include "errabort.h"
 #include "meta.h"
 #include "ra.h"
 
 struct metaTagVal *metaTagValNew(char *tag, char *val)
 /* Create new meta tag/val */
 {
 struct metaTagVal *mtv;
 AllocVar(mtv);
 mtv->tag = cloneString(tag);
 mtv->val = cloneString(val);
 return mtv;
 }
 
+void metaTagValFree(struct metaTagVal **pMtv)
+/* Free up metaTagVal. */
+{
+struct metaTagVal *mtv = *pMtv;
+if (mtv != NULL)
+    {
+    freeMem(mtv->tag);
+    freeMem(mtv->val);
+    freez(pMtv);
+    }
+}
+
+void metaTagValFreeList(struct metaTagVal **pList)
+/* Free a list of dynamically allocated metaTagVal's */
+{
+struct metaTagVal *el, *next;
+
+for (el = *pList; el != NULL; el = next)
+    {
+    next = el->next;
+    metaTagValFree(&el);
+    }
+*pList = NULL;
+}
+
 int metaTagValCmp(const void *va, const void *vb)
 /* Compare to sort based on tag name . */
 {
 const struct metaTagVal *a = *((struct metaTagVal **)va);
 const struct metaTagVal *b = *((struct metaTagVal **)vb);
 return strcmp(a->tag, b->tag);
 }
 
+void metaFree(struct meta **pMeta)
+/* Free up memory associated with a meta. */
+{
+struct meta *meta = *pMeta;
+if (meta != NULL)
+    {
+    metaTagValFreeList(&meta->tagList);
+    freez(pMeta);
+    }
+}
+
+void metaFreeList(struct meta **pList)
+/* Free a list of dynamically allocated meta's. Use metaFreeForest to free children too. */
+{
+struct meta *el, *next;
+
+for (el = *pList; el != NULL; el = next)
+    {
+    next = el->next;
+    metaFree(&el);
+    }
+*pList = NULL;
+}
+
+void metaFreeForest(struct meta **pForest)
+/* Free up all metas in forest and their children. */ 
+{
+struct meta *meta;
+for (meta = *pForest; meta != NULL; meta = meta->next)
+    {
+    if (meta->children)
+         metaFreeForest(&meta->children);
+    }
+metaFreeList(pForest);
+}
+
+
 void metaSortTags(struct meta *meta)
 /* Do canonical sort so that the first tag stays first but the
  * rest are alphabetical. */
 {
 slSort(&meta->tagList->next, metaTagValCmp);
 }
 
 int countLeadingSpacesDetabbing(char *s, int tabStop)
 /* Count up leading chars including those implied by tab. Set tabStop to 8
  * for usual UNIX results. */
 {
 int count = 0;
 char c;
 while ((c = *s++) != 0)
     {
@@ -164,32 +226,32 @@
     struct meta **pList;
     if (forest == NULL)   /* First time. */
         {
 	if (meta->indent != 0)
 	    errAbort("Initial stanza of %s should not be indented", fileName);
 	if (keyTag == NULL)
 	    keyTag = meta->tagList->tag;
 	pList = &forest;
 	}
     else
         {
 	if (!sameString(keyTag, meta->tagList->tag))
 	    {
 	    if (ignoreOtherStanzas)
 	        {
+		metaFree(&meta);
 		continue;
-		// TODO: We should really free memory here. 
 		}
 	    else
 	        errAbort("Stanza beginning with %s instead of %s line %d of %s",
 		    meta->tagList->tag, keyTag, lf->lineIx, lf->fileName);
 	    }
 	if (meta->indent > lastMeta->indent)
 	    {
 	    pList = &lastMeta->children;
 	    meta->parent = lastMeta;
 	    }
 	else if (meta->indent == lastMeta->indent)
 	    {
 	    if (meta->indent == 0)
 		pList = &forest;
 	    else