src/hg/utils/tdbQuery/tdbQuery.c 1.2

1.2 2009/12/02 05:28:46 kent
Handling include files. CHecking for duplicate tags (in non-include stanzas)
Index: src/hg/utils/tdbQuery/tdbQuery.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/utils/tdbQuery/tdbQuery.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -b -B -U 4 -r1.1 -r1.2
--- src/hg/utils/tdbQuery/tdbQuery.c	2 Dec 2009 01:29:58 -0000	1.1
+++ src/hg/utils/tdbQuery/tdbQuery.c	2 Dec 2009 05:28:46 -0000	1.2
@@ -142,46 +142,71 @@
         break;
 return p;
 }
 
-struct tdbRecord *readStartingFromFile(char *fileName, struct lm *lm)
-/* Read in records from file and any files included from it. */
+static void checkDupeFields(struct tdbRecord *record, struct lineFile *lf)
+/* Make sure that each field in record is unique. */
 {
-struct tdbRecord *recordList = NULL, *record;
-struct lineFile *lfStack = NULL, *lf;
-struct hash *circularHash = hashNew(0);
-hashAdd(circularHash, fileName, NULL);
-lf = lineFileOpen(fileName, TRUE);
-uglyf("readStartingFrom %s %p\n", fileName, lm);
-while (lf != NULL)
-    {
-    while ((record = tdbRecordReadOne(lf, "track", lm)) != NULL)
+struct hash *uniqHash = hashNew(0);
+struct tdbField *field;
+for (field = record->fieldList; field != NULL; field = field->next)
+    {
+    if (hashLookup(uniqHash, field->name))
+        errAbort("Duplicate tag %s in record ending line %d of %s", field->name,
+		lf->lineIx, lf->fileName);
+    hashAdd(uniqHash, field->name, NULL);
+    }
+hashFree(&uniqHash);
+}
+
+static void recurseThroughIncludes(char *fileName, struct lm *lm, 
+	struct hash *circularHash,  struct tdbRecord **pRecordList)
+/* Recurse through include files. */
+{
+struct tdbRecord *record;
+struct lineFile *lf = lineFileOpen(fileName, TRUE);
+while ((record = tdbRecordReadOne(lf, "track", lm)) != NULL)
         {
 	struct tdbField *firstField = record->fieldList;
 	if (sameString(firstField->name, "include"))
 	    {
-	    char *includeName = firstField->val;
+	struct tdbField *field;
+	for (field = firstField; field != NULL; field = field->next)
+	    {
+	    if (!sameString(field->name, "include"))
+	       {
+	       errAbort("Non-include tag %s in an include stanza ending line %d of %s", 
+		    field->name, lf->lineIx, lf->fileName);
+	       }
+	    char *relPath = field->val;
+	    char dir[PATH_LEN], name[FILENAME_LEN], extension[FILEEXT_LEN];
+	    splitPath(lf->fileName, dir, NULL, NULL);
+	    char includeName[PATH_LEN];
+	    safef(includeName, sizeof(includeName), "%s%s", dir, relPath);
 	    if (hashLookup(circularHash, includeName))
 	        {
 		errAbort("Including file %s in an infinite loop line %d of %s", 
 			includeName, lf->lineIx, lf->fileName);
 		}
-	    slAddHead(&lfStack, lf);
-	    uglyf("opening include %s\n", includeName);
-	    lf = lineFileOpen(includeName, TRUE);
-	    hashAdd(circularHash, includeName, NULL);
+	    recurseThroughIncludes(includeName, lm, circularHash, pRecordList);
+	    }
 	    }
 	else
 	    {
-	    slAddHead(&recordList, record);
-	    }
+	checkDupeFields(record, lf);
+	slAddHead(pRecordList, record);
 	}
-   uglyf("done with %s\n", lf->fileName);
-   lineFileClose(&lf);
-   lf = lfStack;
-   if (lfStack != NULL)
-       lfStack = lfStack->next;
     }
+lineFileClose(&lf);
+}
+
+struct tdbRecord *readStartingFromFile(char *fileName, struct lm *lm)
+/* Read in records from file and any files included from it. */
+{
+struct tdbRecord *recordList = NULL;
+struct hash *circularHash = hashNew(0);
+recurseThroughIncludes(fileName, lm, circularHash, &recordList);
+hashAdd(circularHash, fileName, NULL);
 hashFree(&circularHash);
 slReverse(&recordList);
 return recordList;
 }
@@ -211,20 +236,23 @@
 for (dbOrder = dbOrderList; dbOrder != NULL; dbOrder = dbOrder->next)
     {
     struct lm *lm = lmInit(0);
     struct dbPath *p = dbOrder->val;
-    struct slName *fileLevelList = dbPathToFiles(p);
-
-    char *fileName = fileLevelList->name;	/* Loop soon */
+    struct slName *fileLevelList = dbPathToFiles(p), *fileLevel;
+    struct hash *recordHash = hashNew(0);
+    for (fileLevel = fileLevelList; fileLevel != NULL; fileLevel = fileLevel->next)
+        {
+	char *fileName = fileLevel->name;
     struct tdbRecord *recordList = readStartingFromFile(fileName, lm);
     uglyf("Read %d records starting from %s\n", slCount(recordList), fileName);
-    struct hash *recordHash = hashNew(0);
     struct tdbRecord *record;
     for (record = recordList; record != NULL; record = record->next)
         {
 	if (record->key != NULL)
 	    hashAdd(recordHash, record->key, record);
 	}
+	}
+
     lmCleanup(&lm);
     }
 
 rqlStatementFree(&rql);