Index: branches/eam-psphot-branch/psLib/src/astronomy/psMetadata.c
===================================================================
--- branches/eam-psphot-branch/psLib/src/astronomy/psMetadata.c	(revision 3678)
+++ branches/eam-psphot-branch/psLib/src/astronomy/psMetadata.c	(revision 3788)
@@ -12,6 +12,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.57 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-03-29 21:31:54 $
+*  @version $Revision: 1.57.4.1 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-04-29 09:17:02 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -68,5 +68,6 @@
 /*****************************************************************************/
 
-static psMetadataItem* makeMetaMulti(psHash* table, const char* key, psMetadataItem* existing)
+# if (0)
+    static psMetadataItem* makeMetaMulti(psHash* table, const char* key, psMetadataItem* existing)
 {
 
@@ -95,4 +96,5 @@
     return item;
 }
+# endif
 
 static void metadataItemFree(psMetadataItem* metadataItem)
@@ -174,5 +176,6 @@
 {
     psMetadataItem* metadataItem = NULL;
-
+    char tmp;
+    int Nbyte;
 
     PS_PTR_CHECK_NULL(name,NULL);
@@ -185,11 +188,10 @@
     p_psMemSetDeallocator(metadataItem, (psFreeFcn) metadataItemFree);
 
-    // Allocate and set metadata item comment
-    metadataItem->comment = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
+    // set metadata item comment
     if (comment == NULL) {
         // Per SDRS, null isn't allowed, must use "" instead
-        strncpy(metadataItem->comment, "", MAX_STRING_LENGTH);
+        metadataItem->comment = psStringCopy ("");
     } else {
-        strncpy(metadataItem->comment, comment, MAX_STRING_LENGTH);
+        metadataItem->comment = psStringCopy (comment);
     }
 
@@ -201,5 +203,6 @@
 
     // Allocate and set metadata item name
-    metadataItem->name = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
+    Nbyte = vsnprintf(&tmp, 0, name, argPtr) + 1;
+    metadataItem->name = (char *)psAlloc(sizeof(char) * Nbyte);
     vsprintf(metadataItem->name, name, argPtr);
 
@@ -220,5 +223,5 @@
     case PS_META_STR:
         // Perform copy of input strings
-        metadataItem->data.V = psStringNCopy(va_arg(argPtr, char *), MAX_STRING_LENGTH);
+        metadataItem->data.V = psStringCopy(va_arg(argPtr, char *));
         break;
     case PS_META_LIST:
@@ -230,7 +233,10 @@
     case PS_META_ASTROM:
     case PS_META_UNKNOWN:
-    case PS_META_MULTI:
         // Copy of input data not performed due to variability of data types
         metadataItem->data.V = psMemIncrRefCounter(va_arg(argPtr, psPtr));
+        break;
+    case PS_META_MULTI:
+        // MULTI needs to create a psList entry, value must be NULL
+        metadataItem->data.list = psListAlloc(NULL);
         break;
     default:
@@ -239,5 +245,4 @@
         metadataItem = NULL;
     }
-
     return metadataItem;
 }
@@ -262,4 +267,31 @@
 
     return metadata;
+}
+
+psBool MetadataAddNewItem (psMetadata *md, psMetadataItem *metadataItem, psS32 location)
+{
+
+    char * key = NULL;
+    psHash *mdTable = NULL;
+    psList *mdList = NULL;
+
+    mdTable = md->table;
+    mdList = md->list;
+    key = metadataItem->name;
+
+    // OK, this is a new item.
+    // Add new metadata item to metadata collection's hash
+    if(!psHashAdd(mdTable, key, metadataItem)) {
+        psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
+        return false;
+    }
+
+    // Add new metadata item to metadata collection's list
+    if(!psListAdd(mdList, location, metadataItem)) {
+        psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
+        return false;
+    }
+    // Success
+    return true;
 }
 
@@ -282,72 +314,85 @@
 
     // See if key is already in table
-    existingEntry = (psMetadataItem*)psHashLookup(mdTable, key);
-
+    existingEntry = psMetadataLookup(md, key);
+
+    if (existingEntry == NULL) {
+        MetadataAddNewItem (md, metadataItem, location);
+        return true;
+    }
+
+    // if existing entry is MULTI, add the new entry to that list
+    // XXX does this behave correctly for adding a MULTI node to an exiting MULTI node?
+    if (existingEntry->type == PS_META_MULTI) {
+        PS_PTR_CHECK_NULL(existingEntry->data.list,NULL);
+
+        // Add new metadata item to multi entry's list (XXX is TAIL correct, or location?)
+        if(!psListAdd(existingEntry->data.list, PS_LIST_TAIL, metadataItem)) {
+            psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
+            return false;
+        }
+
+        // Add new metadata item to metadata collection's list
+        if(!psListAdd(mdList, location, metadataItem)) {
+            psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
+            return false;
+        }
+        return true;
+    }
+
+    // if existing entry is NOT MULTI, we have several choices:
+    //   - new entry is MULTI: move existing entry to new MULTI list
+    //   - DUPLICATE_OK: create a new MULTI and add both old and new to it
+    //   - REPLACE : replace the existing entry with the new entry
+    //   - raise an error
+
+    // incoming entry is PS_META_MULTI  (DUPLICATE_OK is redundant, REPLACE is non-sequitor)
     if (metadataItem->type == PS_META_MULTI) {
-        // the incoming entry is PS_META_MULTI
-
-        // force the hash entry to be PS_META_MULTI
-        existingEntry = makeMetaMulti(mdTable,key,existingEntry);
-
-        // add all the items in the incoming entry to metadata
-        psList* list = metadataItem->data.list;
-        if (list != NULL) {
-            psListIterator* iter = psListIteratorAlloc(list,PS_LIST_HEAD,true);
-            psMetadataItem* listItem;
-            while ((listItem=(psMetadataItem*)psListGetAndIncrement(iter)) != NULL) {
-                psMetadataAddItem(md,listItem,location,flags);
-            }
-            psFree(iter);
-        }
+
+        // replace hash entry with points to existingEntry with new entry
+        psHashAdd (mdTable, key, metadataItem);
+
+        // move the existing hash entry to a node of the new entry
+        psListAdd (metadataItem->data.list, PS_LIST_TAIL, existingEntry);
 
         return true; // all done.
     }
 
-    // how the item is added to the hash depends on prior existence, flags, etc.
-    if(existingEntry != NULL) { // prior existence
-        if (existingEntry->type == PS_META_MULTI || (flags & PS_META_DUPLICATE_OK) != 0) {
-            // duplicate entries allowed - add another entry.
-
-            // make sure the existing entry is PS_META_MULTI
-            existingEntry = makeMetaMulti(mdTable,key,existingEntry);
-
-            // add to the hash's list of duplicate entries
-            if (! psListAdd(existingEntry->data.list, PS_LIST_TAIL, metadataItem) ) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
-                return false;
-            }
-        } else if ((flags & PS_META_REPLACE) != 0) {
-            // replace entry instead of creating a duplicate entry.
-
-            // remove the existing entry from metadata
-            psMetadataRemove(md,0,key);
-
-            // treat as if new (added to list below)
-            if(!psHashAdd(mdTable, key, metadataItem)) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
-                return false;
-            }
-        } else {
-            // default is to error on duplicate entry.
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                    PS_ERRORTEXT_psMetadata_DUPLICATE_NOT_ALLOWED);
-            return false;
-        }
-    } else {
-        // OK, this is a new item.
-
-        // Node doesn't exist - Add new metadata item to metadata collection's hash
-        if(!psHashAdd(mdTable, key, metadataItem)) {
-            psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
-            return false;
-        }
-    }
-
-    if(!psListAdd(mdList, location, metadataItem)) {
-        psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
-        return false;
-    }
-
-    return true;
+    // duplicate entries allowed - create a MULTI with name and add both to it
+    if (flags & PS_META_DUPLICATE_OK) {
+
+        psMetadataItem *multi;
+
+        multi = psMetadataItemAlloc (key, PS_META_MULTI, "multi container", NULL);
+
+        // replace hash entry with points to existingEntry with new multi
+        psHashAdd (mdTable, key, multi);
+
+        // move the existing hash entry to a node of the new entry
+        psListAdd (multi->data.list, PS_LIST_TAIL, existingEntry);
+
+        // move the existing hash entry to a node of the new entry
+        psListAdd (multi->data.list, PS_LIST_TAIL, metadataItem);
+
+        // move the existing hash entry to a node of the new entry
+        psListAdd (mdList, PS_LIST_TAIL, metadataItem);
+
+        return true;
+    }
+
+    if (flags & PS_META_REPLACE) {
+        // replace entry instead of creating a duplicate entry.
+
+        // remove the existing entry from metadata
+        psMetadataRemove(md,0,key);
+
+        // treat as if new (added to list below)
+        MetadataAddNewItem (md, metadataItem, location);
+        return true;
+    }
+
+    // default is to error on duplicate entry.
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+            PS_ERRORTEXT_psMetadata_DUPLICATE_NOT_ALLOWED);
+    return false;
 }
 
