Index: /trunk/Ohana/src/libdvo/include/dvo.h
===================================================================
--- /trunk/Ohana/src/libdvo/include/dvo.h	(revision 41423)
+++ /trunk/Ohana/src/libdvo/include/dvo.h	(revision 41424)
@@ -1135,4 +1135,9 @@
 SkyList   *SkyListChildrenByBounds_List PROTO((SkyList *table, int depth, double Rmin, double Rmax, double Dmin, double Dmax));
 
+/* APIs to split and extend a skytable */
+void       SkyTableL5fromL4_List   PROTO((SkyRegion *L4, SkyTable *L5, int Nfirst));
+void       SkyTableExtend          PROTO((SkyTable *old, SkyTable *new, int depth));
+
+
 int set_skyregion(double Rs, double Re, double Ds, double De);
 int get_skyregion (double *Rs, double *Re, double *Ds, double *De);
Index: /trunk/Ohana/src/libdvo/src/skyregion_gsc.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/skyregion_gsc.c	(revision 41423)
+++ /trunk/Ohana/src/libdvo/src/skyregion_gsc.c	(revision 41424)
@@ -39,4 +39,9 @@
 int NsetForDecRange (float dDec);
 void SkyRegionPrint (SkyRegion *region);
+
+void SkyTableExtend (SkyTable *old, SkyTable *new, int depth);
+void SkyTableL5fromL4_List (SkyRegion *L4, SkyTable *L5, int Nfirst);
+
+void SkyTableValidate (SkyTable *table);
 
 SkyTable *SkyTableFromGSC (char *filename, int depth, int VERBOSE) {
@@ -160,4 +165,6 @@
   skytable[0].Nregions = 0;
 
+  skytable[0].filename = NULL;
+
   // define the host table filename
   strcpy (skytable->hosts, "HostTable.dat");
@@ -171,7 +178,18 @@
   SkyTableAppend (skytable, &L2, skytable[0].Nregions - L1.Nregions);
   SkyTableAppend (skytable, &L3, skytable[0].Nregions - L2.Nregions);
+  SkyTableAppend (skytable, &L4, skytable[0].Nregions - L3.Nregions);
+
+  SkyTableValidate (skytable);
+
+  free (L0.regions);
+  free (L1.regions);
+  free (L2.regions);
+  free (L3.regions);
+  free (L4.regions);
+  gfits_free_header (&theader);
+  gfits_free_table (&ftable);
 
   // XXX TEST : for L4 entries in a certain ra,dec range, generate L5 entries:
-
+# if (0)
   SkyTable L5; 
   L5.Nregions = 0;
@@ -189,16 +207,7 @@
   }
 
-  SkyTableAppend (skytable, &L4, skytable[0].Nregions - L3.Nregions);
-
   SkyTableAppend (skytable, &L5, skytable[0].Nregions - L4.Nregions);
   free (L5.regions);
-
-  free (L0.regions);
-  free (L1.regions);
-  free (L2.regions);
-  free (L3.regions);
-  free (L4.regions);
-  gfits_free_header (&theader);
-  gfits_free_table (&ftable);
+# endif
 
   /* fix the depth elements and create the filename array */
@@ -208,4 +217,22 @@
     skytable[0].regions[i].table = (skytable[0].regions[i].depth == depth);
   }
+
+  // XXX TEST : for L4 entries in a certain ra,dec range, generate L5 entries:
+# if (0)
+  SkyTable L5; 
+  L5.Nregions = 0;
+  L5.Nalloc   = 1000;
+  ALLOCATE (L5.regions, SkyRegion, L5.Nalloc);
+
+  // get a list of the SkyRegions which overlap the point at the depth (only 1)
+  SkyList *skylist = SkyRegionByPoint (skytable, 4, 10.0, 40.0);
+
+  for (i = 0; i < skylist->Nregions; i++) {
+    SkyTableL5fromL4_List (skylist->regions[i], &L5, skytable->Nregions);
+  }
+
+  SkyTableExtend (skytable, &L5, depth);
+  free (L5.regions);
+# endif
 
   // ohana_memdump (0);
@@ -565,4 +592,6 @@
 }
 
+int NDIV_L5 = 5;
+
 // append new regions on to the supplied L5 list (may be empty)
 void SkyTableL5fromL4 (SkyRegion *L4, SkyTable *L5) {
@@ -573,5 +602,5 @@
 
   Nr = L5[0].Nregions;
-  L5[0].Nregions += NDIV*NDIV;
+  L5[0].Nregions += NDIV_L5*NDIV_L5;
   CHECK_REALLOCATE (L5[0].regions, SkyRegion, L5[0].Nalloc, L5[0].Nregions, 0.5*L5[0].Nalloc);
 
@@ -582,13 +611,13 @@
   // XXX handle the pole regions just a bit differently...
 
-  /* subdivide L4 into NDIV boxes */
+  /* subdivide L4 into NDIV_L5 boxes */
   Rmin = L4[0].Rmin;
   Dmin = L4[0].Dmin;
-  dR = (L4[0].Rmax - L4[0].Rmin) / NDIV;
-  dD = (L4[0].Dmax - L4[0].Dmin) / NDIV;
+  dR = (L4[0].Rmax - L4[0].Rmin) / NDIV_L5;
+  dD = (L4[0].Dmax - L4[0].Dmin) / NDIV_L5;
 
   Nbox = 0;
-  for (ny = 0; ny < NDIV; ny ++) {
-    for (nx = 0; nx < NDIV; nx ++) {
+  for (ny = 0; ny < NDIV_L5; ny ++) {
+    for (nx = 0; nx < NDIV_L5; nx ++) {
       L5[0].regions[Nr].Rmin     = Rmin  + (nx + 0)*dR;
       L5[0].regions[Nr].Rmax     = Rmin  + (nx + 1)*dR;
@@ -618,5 +647,88 @@
 }
 
+// append new regions on to the supplied L5 list (may be empty)
+void SkyTableL5fromL4_List (SkyRegion *L4, SkyTable *L5, int Nfirst) {
+
+  int nx, ny, Nr, Nbox;
+  double Rmin, Dmin, dR, dD;
+  char name[80];
+
+  Nr = L5[0].Nregions;
+  L5[0].Nregions += NDIV_L5*NDIV_L5;
+  CHECK_REALLOCATE (L5[0].regions, SkyRegion, L5[0].Nalloc, L5[0].Nregions, 0.5*L5[0].Nalloc);
+
+  // Nfirst is the index value which the first entry in the new table of regions would get.
+
+  // These child ranges are relative to the index of the first entry in this L5 region.
+  // This is the value of Nregions of the full table.
+
+  L4[0].child  = TRUE;
+  L4[0].childS = Nfirst + Nr;
+  L4[0].childE = Nfirst + L5[0].Nregions;
+
+  // XXX handle the pole regions just a bit differently...
+
+  /* subdivide L4 into NDIV_L5 boxes */
+  Rmin = L4[0].Rmin;
+  Dmin = L4[0].Dmin;
+  dR = (L4[0].Rmax - L4[0].Rmin) / NDIV_L5;
+  dD = (L4[0].Dmax - L4[0].Dmin) / NDIV_L5;
+
+  Nbox = 0;
+  for (ny = 0; ny < NDIV_L5; ny ++) {
+    for (nx = 0; nx < NDIV_L5; nx ++) {
+      L5[0].regions[Nr].Rmin     = Rmin  + (nx + 0)*dR;
+      L5[0].regions[Nr].Rmax     = Rmin  + (nx + 1)*dR;
+      L5[0].regions[Nr].Dmin     = Dmin + (ny + 0)*dD;
+      L5[0].regions[Nr].Dmax     = Dmin + (ny + 1)*dD;
+
+      L5[0].regions[Nr].index    =  Nfirst + Nr;
+      L5[0].regions[Nr].depth    =  5;
+      L5[0].regions[Nr].table    =  -1;
+      L5[0].regions[Nr].parent   =  L4[0].index;
+      L5[0].regions[Nr].child    =  FALSE;
+      L5[0].regions[Nr].childS   =  0;
+      L5[0].regions[Nr].childE   =  0;
+      L5[0].regions[Nr].hostFlags = 0;
+      L5[0].regions[Nr].hostID    = 0;
+      L5[0].regions[Nr].backupID  = 0;
+
+      myAssert (snprintf (name, 80, "%s.%02d", L4[0].name, Nbox) < 80, "overflow");
+      strcpy (L5[0].regions[Nr].name, name);
+      if (DEBUG >= 4) SkyRegionPrint (&L5[0].regions[Nr]);
+
+      Nr ++;
+      Nbox ++;
+    }
+  }
+  return;
+}
+
+// add the supplied skytable regions to the end.
+// the parent, child, and index values are already correct
+void SkyTableExtend (SkyTable *old, SkyTable *new, int depth) {
+
+  int i, Nold;
+
+  Nold = old[0].Nregions;
+
+  old[0].Nregions += new[0].Nregions;
+  REALLOCATE (old[0].regions,  SkyRegion, old[0].Nregions);
+  REALLOCATE (old[0].filename, char *,    old[0].Nregions);
+
+  for (i = 0; i < new[0].Nregions; i++) {
+    old[0].regions[i + Nold] = new[0].regions[i];
+    old[0].regions[i + Nold].table = (old[0].regions[i + Nold].depth == depth);
+    old[0].filename[i + Nold] = NULL;
+  }
+  return;
+}
+
 // memory neutral
+
+/* We have a skytable with a certain number of entries.
+   Add the new entries on to the end of this table
+ */
+
 void SkyTableAppend (SkyTable *old, SkyTable *new, int Nprev) {
 
@@ -628,4 +740,6 @@
   REALLOCATE (old[0].regions, SkyRegion, old[0].Nregions);
 
+  // this code assumes that the parents of all supplied
+  // new regions are the last block of regions
   for (i = Nprev; i < Nold; i++) {
     old[0].regions[i].childS += Nold;
@@ -635,7 +749,35 @@
   for (i = 0; i < new[0].Nregions; i++) {
     old[0].regions[i + Nold] = new[0].regions[i];
-    old[0].regions[i + Nold].parent += Nold;
+    old[0].regions[i + Nold].parent += Nprev;
     old[0].regions[i + Nold].index += Nold;
   }
+  return;
+}
+
+void SkyTableValidate (SkyTable *table) {
+
+  for (int i = 0; i < table[0].Nregions; i++) {
+    int idx = table[0].regions[i].index; // my index
+
+    // index should match sequence
+    myAssert (i == idx, "bad index");
+
+    int parent = table[0].regions[i].parent;
+    if (parent != -1) {
+      // my index should be in the range of my parent's children
+      myAssert (idx >= table[0].regions[parent].childS, "bad childS");
+      myAssert (idx  < table[0].regions[parent].childE, "bad childE");
+    }
+    int Ns = table[0].regions[i].childS;
+    int Ne = table[0].regions[i].childE;
+    if (Ns && Ne) {
+      for (int j = Ns; j < Ne; j++) {
+	// my children should all have my index as the parent
+	myAssert (table[0].regions[j].parent == idx, "bad parent");
+      }
+    }
+  }
+
+  fprintf (stderr, "validated skytable\n");
   return;
 }
Index: /trunk/Ohana/src/libdvo/src/skyregion_ops.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/skyregion_ops.c	(revision 41423)
+++ /trunk/Ohana/src/libdvo/src/skyregion_ops.c	(revision 41424)
@@ -116,5 +116,7 @@
 
   list[0].regions[0] = &region[No];
-  list[0].filename[0] = table[0].filename[No];
+  if (table[0].filename) {
+    list[0].filename[0] = table[0].filename[No];
+  }
   list[0].Nregions = 1;
   return (list);
