Index: /trunk/psLib/pslib.kdevses
===================================================================
--- /trunk/psLib/pslib.kdevses	(revision 3380)
+++ /trunk/psLib/pslib.kdevses	(revision 3381)
@@ -4,17 +4,17 @@
  <DocsAndViews NumberOfDocuments="5" >
   <Doc0 NumberOfViews="1" URL="file:/home/desonia/panstarrs/psLib/src/astronomy/psMetadata.c" >
-   <View0 line="129" Type="Source" />
+   <View0 line="593" Type="Source" />
   </Doc0>
   <Doc1 NumberOfViews="1" URL="file:/home/desonia/panstarrs/psLib/src/astronomy/psMetadata.h" >
-   <View0 line="164" Type="Source" />
+   <View0 line="103" Type="Source" />
   </Doc1>
-  <Doc2 NumberOfViews="1" URL="file:/home/desonia/panstarrs/psLib/src/astronomy/astronomy.i" >
-   <View0 line="16" Type="Source" />
+  <Doc2 NumberOfViews="1" URL="file:/home/desonia/panstarrs/psLib/src/collections/psList.h" >
+   <View0 line="79" Type="Source" />
   </Doc2>
-  <Doc3 NumberOfViews="1" URL="file:/home/desonia/panstarrs/psLib/src/astronomy/psMetadataIO.c" >
-   <View0 line="965" Type="Source" />
+  <Doc3 NumberOfViews="1" URL="file:/home/desonia/panstarrs/psLib/src/astronomy/psAstronomyErrors.dat" >
+   <View0 line="50" Type="Source" />
   </Doc3>
-  <Doc4 NumberOfViews="1" URL="file:/home/desonia/panstarrs/psLib/src/sysUtils/psType.h" >
-   <View0 line="0" Type="Source" />
+  <Doc4 NumberOfViews="1" URL="file:/home/desonia/panstarrs/psLib/src/collections/psList.c" >
+   <View0 line="216" Type="Source" />
   </Doc4>
  </DocsAndViews>
Index: /trunk/psLib/src/astronomy/psAstronomyErrors.dat
===================================================================
--- /trunk/psLib/src/astronomy/psAstronomyErrors.dat	(revision 3380)
+++ /trunk/psLib/src/astronomy/psAstronomyErrors.dat	(revision 3381)
@@ -47,4 +47,7 @@
 psMetadata_FIND_FAILED                 Could not find metadata item, %s.
 psMetadata_FIND_INDEX_FAILED           Could not find metadata item at index %d.
+psMetadata_DUPLICATE_NOT_ALLOWED       Duplicate metadata item name is not allowed.  Use a psMetadataFlags option to allow such action.
+psMetadata_REGEX_INVALID               Specified regular expression is invalid.  %s.
+psMetadata_LOCATION_INVALID            Specified location, %d, is invalid.
 #
 psMetadataIO_TYPE_INVALID              Specified type, %d, is not supported.
Index: /trunk/psLib/src/astronomy/psAstronomyErrors.h
===================================================================
--- /trunk/psLib/src/astronomy/psAstronomyErrors.h	(revision 3380)
+++ /trunk/psLib/src/astronomy/psAstronomyErrors.h	(revision 3381)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-02-28 23:34:10 $
+ *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-03-07 20:58:50 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -65,4 +65,7 @@
 #define PS_ERRORTEXT_psMetadata_FIND_FAILED "Could not find metadata item, %s."
 #define PS_ERRORTEXT_psMetadata_FIND_INDEX_FAILED "Could not find metadata item at index %d."
+#define PS_ERRORTEXT_psMetadata_DUPLICATE_NOT_ALLOWED "Duplicate metadata item name is not allowed.  Use a psMetadataFlags option to allow such action."
+#define PS_ERRORTEXT_psMetadata_REGEX_INVALID "Specified regular expression is invalid.  %s."
+#define PS_ERRORTEXT_psMetadata_LOCATION_INVALID "Specified location, %d, is invalid."
 #define PS_ERRORTEXT_psMetadataIO_TYPE_INVALID "Specified type, %d, is not supported."
 #define PS_ERRORTEXT_psMetadataIO_EXTNUM_NOTPOSITIVE "Specified extension number, %d, is invalid.  Value must be positive if no extension name is given."
Index: /trunk/psLib/src/astronomy/psMetadata.c
===================================================================
--- /trunk/psLib/src/astronomy/psMetadata.c	(revision 3380)
+++ /trunk/psLib/src/astronomy/psMetadata.c	(revision 3381)
@@ -12,6 +12,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.53 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.54 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -85,4 +85,13 @@
 }
 
+static void metadataIteratorFree(psMetadataIterator* iter)
+{
+    if (iter == NULL) {
+        return;
+    }
+    psFree(iter->iter);
+    regfree(iter->preg);
+}
+
 static void metadataFree(psMetadata* metadata)
 {
@@ -158,5 +167,5 @@
 
     // Set metadata item type
-    metadataItem->type = type;
+    metadataItem->type = type & PS_METADATA_TYPE_MASK;
 
     // Allocate and set metadata item name
@@ -165,5 +174,5 @@
 
     // Set metadata item value
-    switch(type) {
+    switch(metadataItem->type) {
     case PS_META_BOOL:
         metadataItem->data.B = (psBool)va_arg(argPtr, psS32);
@@ -190,4 +199,5 @@
     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));
@@ -223,5 +233,5 @@
 }
 
-psBool psMetadataAddItem(psMetadata *md, psMetadataItem *metadataItem, psS32 location)
+psBool psMetadataAddItem(psMetadata *md, psMetadataItem *metadataItem, psS32 location, psS32 flags)
 {
     char * key = NULL;
@@ -229,6 +239,4 @@
     psList *mdList = NULL;
     psMetadataItem *existingEntry = NULL;
-    psMetadataItem *newFolderEntry = NULL;
-    psMetadataType newType;
 
     PS_PTR_CHECK_NULL(md,NULL);
@@ -238,5 +246,4 @@
     PS_PTR_CHECK_NULL(metadataItem->name,NULL);
 
-    newType = metadataItem->type;
     mdTable = md->table;
     mdList = md->list;
@@ -245,72 +252,56 @@
     // See if key is already in table
     existingEntry = (psMetadataItem*)psHashLookup(mdTable, key);
+
+    // how the item is added to the hash depends on flags & prior existence
     if(existingEntry != NULL) {
-
-        if(existingEntry->type == PS_META_LIST) {
-
-            if(existingEntry->data.list == NULL) {
-                existingEntry->data.list = psListAlloc(NULL);
+        if ((flags & PS_META_DUPLICATE_OK) != 0) {
+            // duplicate entries allowed - add another entry.
+            if (existingEntry->type != PS_META_MULTI) {
+                // first duplicate, transfer the hash's old entry into a
+                // list of entries with the type PS_META_MULTI.
+
+                // add entry to a list and dereference the local pointer
+                psList* newList = psListAlloc(existingEntry);
+
+                existingEntry = psMetadataItemAlloc(key,
+                                                    PS_META_MULTI,
+                                                    "",
+                                                    newList);
+                psHashRemove(mdTable,key); // take out the old entry
+                psHashAdd(mdTable, key, existingEntry); // put in the new entry
+
+                // free local references of newly allocated items.
+                psFree(newList);
+                psFree(existingEntry);
+
             }
 
-            // Add leaf node to existing folder node
-            if(!psListAdd(existingEntry->data.list, PS_LIST_TAIL, metadataItem)) {
-                psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_ADD_LIST_FAILED, metadataItem->name);
+            // 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(existingEntry->type != PS_META_LIST && newType!= PS_META_LIST) {
-
-            // Leaf node replaces another leaf. Make new folder node and add leaves.
-            newFolderEntry = psMetadataItemAlloc(key, PS_META_LIST, NULL, NULL);
-            newFolderEntry->data.list = psListAlloc(NULL);
-
-            if(!psListAdd(newFolderEntry->data.list, PS_LIST_TAIL, existingEntry)) {
-                psError(PS_ERR_UNKNOWN,false, PS_ERRORTEXT_psMetadata_ADD_LIST_FAILED,key);
-                psFree(newFolderEntry);
-                return false;
-            }
-
-            if(!psListAdd(newFolderEntry->data.list, PS_LIST_TAIL, metadataItem)) {
-                psError(PS_ERR_UNKNOWN,false, PS_ERRORTEXT_psMetadata_ADD_LIST_FAILED,key);
-                psFree(newFolderEntry);
-                return false;
-            }
-
-            if(!psHashRemove(mdTable, key)) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED,key);
-                psFree(newFolderEntry);
-                return false;
-            }
-
-            if(!psHashAdd(mdTable, key, newFolderEntry)) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
-                psFree(newFolderEntry);
-                return false;
-            }
-
-            // Remove local reference to new folder node
-            psMemDecrRefCounter(newFolderEntry);
-        } else {
-
-            // Folder node replaces leaf or folder node - Put old node into new folder and remove from table
-            if(metadataItem->data.list == NULL) {
-                metadataItem->data.list = psListAlloc(NULL);
-            }
-
-            if(!psListAdd(metadataItem->data.list, PS_LIST_TAIL, existingEntry)) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_LIST_FAILED,key);
-                return false;
-            }
-
-            if(!psHashRemove(mdTable, key)) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED,key);
-                return false;
-            }
-
+            // (added to list below)
+
+        } else if ((flags & PS_META_REPLACE) != 0) {
+            // replace entry instead of creating a duplicate entry.
+
+            // remove the existing entry from metadata
+            psListRemoveData(mdList, existingEntry);
+            psHashRemove(mdTable, 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
@@ -321,11 +312,7 @@
     }
 
-    // Add items to metadata collection's list, even if they have the same metadata item names. Folder nodes
-    // (PS_META_LIST metadata items) are not added, since the metadata list is flat.
-    if(metadataItem->type != PS_META_LIST) {
-        if(!psListAdd(mdList, location, metadataItem)) {
-            psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
-            return false;
-        }
+    if(!psListAdd(mdList, location, metadataItem)) {
+        psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
+        return false;
     }
 
@@ -333,15 +320,24 @@
 }
 
-psBool psMetadataAdd(psMetadata *md, psS32 where, const char *name,
-                     psMetadataType type, const char *comment, ...)
+psBool psMetadataAdd(psMetadata *md, psS32 location, const char *name,
+                     psS32 type, const char *comment, ...)
 {
     va_list argPtr;
+
+    va_start(argPtr, comment);
+    psBool result = psMetadataAddV(md,location,name,type,comment,argPtr);
+    va_end(argPtr);
+
+    return result;
+}
+
+psBool psMetadataAddV(psMetadata *md, psS32 location, const char *name,
+                      psS32 type, const char *comment, va_list list)
+{
     psMetadataItem* metadataItem = NULL;
 
-    va_start(argPtr, comment);
-    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
-    va_end(argPtr);
-
-    if (!psMetadataAddItem(md, metadataItem, where)) {
+    metadataItem = psMetadataItemAllocV(name, type & PS_METADATA_TYPE_MASK, comment, list);
+
+    if (!psMetadataAddItem(md, metadataItem, location, type & PS_METADATA_FLAGS_MASK)) {
         psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_FAILED);
         psFree(metadataItem);
@@ -373,51 +369,72 @@
 psBool psMetadataRemove(psMetadata *md, psS32 where, const char *key)
 {
-    psList* mdList = NULL;
-    psHash* mdTable = NULL;
-    psMetadataItem* entry = NULL;
-
-
     PS_PTR_CHECK_NULL(md,NULL);
+
+    PS_PTR_CHECK_NULL(md->list,NULL);
+    psList* mdList = md->list;
+
     PS_PTR_CHECK_NULL(md->table,NULL);
-    PS_PTR_CHECK_NULL(md->list,NULL);
-
-    mdList = md->list;
-    mdTable = md->table;
+    psHash* mdTable = md->table;
 
     // Select removal by key or index
     if (key != NULL) {
-
         // Remove by key name
-        entry = (psMetadataItem*)psHashLookup(mdTable, key);
+        psMetadataItem* entry = psHashLookup(mdTable,key);
         if (entry == NULL) {
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_FIND_FAILED, key);
+            psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
             return false;
         }
-
+        if (entry->type == PS_META_MULTI) {
+            psMetadataItem* listItem;
+            psListIterator* iter = psListIteratorAlloc(
+                                       entry->data.list,
+                                       PS_LIST_HEAD,true);
+            while ((listItem=psListGetAndIncrement(iter)) != NULL) {
+                psListRemoveData(mdList, listItem);
+            }
+            psFree(iter);
+            psHashRemove(mdTable,key);
+
+        } else {
+            psListRemoveData(mdList, entry);
+            psHashRemove(mdTable, key);
+        }
     } else {
-
         // Remove by index
-        entry = psListGet(mdList, where);
+        psMetadataItem* entry = psListGet(mdList, where);
         if (entry == NULL) {
             psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_FIND_INDEX_FAILED, where);
             return false;
         }
-
         key = entry->name;
-        if(key == NULL) {
+
+        if (key == NULL) {
             psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_REMOVE_LIST_INDEX_FAILED, where);
             return false;
         }
-    }
-
-    if (!psListRemoveData(mdList, entry)) {
-        psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_LIST_FAILED, key);
-        return false;
-    }
-
-    // Remove entry from metadata collection's table
-    if (!psHashRemove(mdTable, key)) {
-        psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
-        return false;
+
+        psMetadataItem* tableItem = psHashLookup(mdTable, key);
+        if (tableItem == NULL) {
+            psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
+            return false;
+        }
+
+        if (tableItem->type == PS_META_MULTI) {
+            // multiple entries with same key, remove just the specified one
+            psListRemoveData(tableItem->data.list, entry);
+            if (psListGet(tableItem->data.list,PS_LIST_HEAD) == NULL) {
+                // list is empty, so let's clear the whole entry now.
+                if (!psHashRemove(mdTable, key)) {
+                    psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
+                    return false;
+                }
+            }
+        } else {
+            if (!psHashRemove(mdTable, key)) {
+                psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
+                return false;
+            }
+        }
+        psListRemove(mdList, where);
     }
 
@@ -455,4 +472,8 @@
         }
         return NULL;
+    }
+    if (metadataItem->type == PS_META_MULTI) {
+        // if multiple keys found, use the first.
+        metadataItem = (psMetadataItem*)((metadataItem->data.list)->head);
     }
 
@@ -486,4 +507,8 @@
         } \
         return 0; \
+    } \
+    if (metadataItem->type == PS_META_MULTI) { \
+        /* if multiple keys found, use the first. */ \
+        metadataItem = (psMetadataItem*)((metadataItem->data.list)->head); \
     } \
     \
@@ -535,2 +560,145 @@
     return entry;
 }
+
+psMetadataIterator* psMetadataIteratorAlloc(psMetadata* md,
+        int location,
+        const char* regex)
+{
+    PS_PTR_CHECK_NULL(md,NULL);
+    PS_PTR_CHECK_NULL(md->list,NULL);
+
+    psMetadataIterator* newIter = psAlloc(sizeof(psMetadataIterator));
+    newIter->preg = NULL;
+    newIter->iter = NULL;
+
+    // Set deallocator
+    p_psMemSetDeallocator(newIter, (psFreeFcn) metadataIteratorFree);
+
+    if (regex == NULL) {
+        newIter->iter = psListIteratorAlloc(md->list, location, false);
+        return newIter;
+    } else {
+        int regRtn = regcomp(newIter->preg,regex,0);
+        if (regRtn != 0) {
+            char errMsg[256];
+            regerror(regRtn, newIter->preg, errMsg, 256);
+            regfree(newIter->preg);
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    PS_ERRORTEXT_psMetadata_REGEX_INVALID,
+                    errMsg);
+            psFree(newIter);
+            return NULL;
+        }
+    }
+
+    psMetadataIteratorSet(newIter, location); // XXX: do we error if no match is found?
+
+    return newIter;
+}
+
+psBool psMetadataIteratorSet(psMetadataIterator* iterator,
+                             int location)
+{
+    int match;
+    psMetadataItem* cursor;
+
+    PS_PTR_CHECK_NULL(iterator,NULL);
+
+    psListIterator* iter = iterator->iter;
+    PS_PTR_CHECK_NULL(iterator->iter,NULL);
+
+    regex_t* preg = iterator->preg;
+
+    // handle trivial case where no regex subsetting is required.
+    if (preg == NULL) {
+        return psListIteratorSet(iter,location);
+    }
+
+    if (location < 0) {
+        // match from the tail
+        match = 0;
+        psListIteratorSet(iter,PS_LIST_TAIL);
+        while ( (cursor=(psMetadataItem*)iter->cursor) != NULL) {
+            if (regexec(preg, cursor->name, 0, NULL, 0) == 0) {
+                // this key is a match
+                match--;
+                if (match == location) {
+                    break;
+                }
+            }
+            (void)psListGetAndDecrement(iter);
+        }
+        return (match == location);
+    }
+
+    // find the n-th match from the head
+    match = -1;
+    psListIteratorSet(iter,PS_LIST_HEAD);
+    while ( (cursor=(psMetadataItem*)iter->cursor) != NULL) {
+        if (regexec(preg, cursor->name, 0, NULL, 0) == 0) {
+            // this key is a match
+            match++;
+            if (match == location) {
+                break;
+            }
+        }
+        (void)psListGetAndIncrement(iter);
+    }
+    return (match == location);
+}
+
+psMetadataItem* psMetadataGetAndIncrement(psMetadataIterator* iterator)
+{
+    psMetadataItem* oldValue;
+
+    PS_PTR_CHECK_NULL(iterator,NULL);
+
+    psListIterator* iter = iterator->iter;
+    PS_PTR_CHECK_NULL(iterator->iter,NULL);
+
+    regex_t* preg = iterator->preg;
+
+    // handle trivial case where no regex subsetting is required.
+    if (preg == NULL) {
+        return (psMetadataItem*)psListGetAndIncrement(iter);
+    }
+
+    oldValue = (psMetadataItem*)iter->cursor;
+
+    while (psListGetAndIncrement(iter) != NULL) {
+        if (iter->cursor != NULL &&
+                regexec(preg, ((psMetadataItem*)iter->cursor)->name, 0, NULL, 0) == 0) {
+            // this key is a match
+            break;
+        }
+    }
+    return oldValue;
+}
+
+psMetadataItem* psMetadataGetAndDecrement(psMetadataIterator* iterator)
+{
+    psMetadataItem* oldValue;
+
+    PS_PTR_CHECK_NULL(iterator,NULL);
+
+    psListIterator* iter = iterator->iter;
+    PS_PTR_CHECK_NULL(iterator->iter,NULL);
+
+    regex_t* preg = iterator->preg;
+
+    // handle trivial case where no regex subsetting is required.
+    if (preg == NULL) {
+        return (psMetadataItem*)psListGetAndDecrement(iter);
+    }
+
+    oldValue = (psMetadataItem*)iter->cursor;
+
+    while (psListGetAndDecrement(iter) != NULL) {
+        if (iter->cursor != NULL &&
+                regexec(preg, ((psMetadataItem*)iter->cursor)->name, 0, NULL, 0) == 0) {
+            // this key is a match
+            break;
+        }
+    }
+    return oldValue;
+}
Index: /trunk/psLib/src/astronomy/psMetadata.h
===================================================================
--- /trunk/psLib/src/astronomy/psMetadata.h	(revision 3380)
+++ /trunk/psLib/src/astronomy/psMetadata.h	(revision 3381)
@@ -11,6 +11,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.38 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.39 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -21,4 +21,6 @@
 #include <stdarg.h>
 #include <stdio.h>
+#include <sys/types.h>
+#include <regex.h>
 
 #include "psHash.h"
@@ -35,8 +37,8 @@
  */
 typedef enum {
-    PS_META_S32,                       ///< Primitive data.
-    PS_META_F32,                       ///< Primitive data.
-    PS_META_F64,                       ///< Primitive data.
-    PS_META_BOOL,                       ///< Primitive data.
+    PS_META_S32,                       ///< psS32 primitive data.
+    PS_META_F32,                       ///< psF32 primitive data.
+    PS_META_F64,                       ///< psF64 primitive data.
+    PS_META_BOOL,                      ///< psBool primitive data.
     PS_META_LIST,                      ///< List data (Stored as item.data.list).
     PS_META_STR,                       ///< String data (Stored as item.data.V).
@@ -49,4 +51,5 @@
     PS_META_ASTROM,                    ///< Astrometric coefficients (Stored as item.data.V).
     PS_META_UNKNOWN,                   ///< Other data (Stored as item.data.V).
+    PS_META_MULTI,                     ///< Used internally, do not create an metadata item of this type.
     PS_META_NTYPE                      ///< Number of types. Must be last.
 } psMetadataType;
@@ -72,6 +75,10 @@
 typedef enum {
     PS_META_DEFAULT = 0,               ///< default behaviour (duplicate entry is an error)
-    PS_META_REPLACE = 0x10000          ///< allow entry to be replaced
+    PS_META_REPLACE = 0x1000000,       ///< allow entry to be replaced
+    PS_META_DUPLICATE_OK = 0x2000000   ///< allow duplicate entries
 } psMetadataFlags;
+
+#define PS_METADATA_FLAGS_MASK 0xFF000000
+#define PS_METADATA_TYPE_MASK 0x00FFFFFF
 
 /** Metadata data structure.
@@ -88,4 +95,16 @@
 }
 psMetadata;
+
+/** Metadata iterator
+ *
+ *  Iterator for metadata.
+ */
+typedef struct
+{
+    psListIterator* iter;              ///< iterator for the psMetadata's psList
+    regex_t* preg;                     ///< the subsetting regular expression
+}
+psMetadataIterator;
+
 
 /** Metadata item data structure.
@@ -134,32 +153,67 @@
 );
 
+/** Create a metadata item with specified string data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocStr(
-    const char* name,
-    const char* comment,
-    const char* value
-);
-
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    const char* value                  ///< the value of the metadata item.
+);
+
+/** Create a metadata item with specified psF32 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocF32(
-    const char* name,
-    const char* comment,
-    psF32 value
-);
-
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psF32 value                        ///< the value of the metadata item.
+);
+
+/** Create a metadata item with specified psF64 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocF64(
-    const char* name,
-    const char* comment,
-    psF64 value
-);
-
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psF64 value                        ///< the value of the metadata item.
+);
+
+/** Create a metadata item with specified psS32 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocS32(
-    const char* name,
-    const char* comment,
-    psS32 value
-);
-
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psS32 value                        ///< the value of the metadata item.
+);
+
+/** Create a metadata item with specified psBool data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocBool(
-    const char* name,
-    const char* comment,
-    psBool value
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psBool value                       ///< the value of the metadata item.
 );
 
@@ -207,5 +261,6 @@
     psMetadata*  md,                   ///< Metadata collection to insert metadat item.
     psMetadataItem*  item,             ///< Metadata item to be added.
-    psS32 location                     ///< Location to be added.
+    psS32 location,                    ///< Location to be added.
+    psS32 flags                        ///< Options flag mask, see psMetadataFlags enum
 );
 
@@ -218,30 +273,47 @@
 psBool psMetadataAdd(
     psMetadata* md,                    ///< Metadata collection to insert metadat item.
-    psS32 where,                       ///< Location to be added.
+    psS32 location,                    ///< Location to be added.
     const char *name,                  ///< Name of metadata item.
-    psMetadataType type,               ///< Type of metadata item.
+    int type,                          ///< Type of metadata item (psMetadataType) and options (psMetadataFlags)
     const char *comment,               ///< Comment for metadata item.
     ...                                ///< Arguments for name formatting and metadata item data.
 );
 
-psBool psMetadataAddS32(psMetadata* md, psS32 where, const char* name,
+#ifndef SWIG
+/** Create and add a metadata item to metadata collection.
+ *
+ * Creates a new metadata item add to the metadata collection.
+ *
+ * @return bool: True for success, false for failure.
+ */
+psBool psMetadataAddV(
+    psMetadata* md,                    ///< Metadata collection to insert metadat item.
+    psS32 location,                    ///< Location to be added.
+    const char *name,                  ///< Name of metadata item.
+    int type,                          ///< Type of metadata item (psMetadataType) and options (psMetadataFlags)
+    const char *comment,               ///< Comment for metadata item.
+    va_list list                       ///< Arguments for name formatting and metadata item data.
+);
+#endif
+
+psBool psMetadataAddS32(psMetadata* md, psS32 location, const char* name,
                         const char* comment, psS32 value);
-psBool psMetadataAddF32(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddF32(psMetadata* md, psS32 location, const char* name,
                         const char* comment, psF32 value);
-psBool psMetadataAddF64(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddF64(psMetadata* md, psS32 location, const char* name,
                         const char* comment, psF64 value);
-psBool psMetadataAddList(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddList(psMetadata* md, psS32 location, const char* name,
                          const char* comment, psList* value);
-psBool psMetadataAddStr(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddStr(psMetadata* md, psS32 location, const char* name,
                         const char* comment, const char* value);
-psBool psMetadataAddVector(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddVector(psMetadata* md, psS32 location, const char* name,
                            const char* comment, psVector* value);
-psBool psMetadataAddImage(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddImage(psMetadata* md, psS32 location, const char* name,
                           const char* comment, psImage* value);
-psBool psMetadataAddHash(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddHash(psMetadata* md, psS32 location, const char* name,
                          const char* comment, psHash* value);
-psBool psMetadataAddLookupTable(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddLookupTable(psMetadata* md, psS32 location, const char* name,
                                 const char* comment, psLookupTable* value);
-psBool psMetadataAddUnknown(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddUnknown(psMetadata* md, psS32 location, const char* name,
                             const char* comment, psPtr value);
 
@@ -340,5 +412,5 @@
  * @return void* : Value of metadata item.
  */
-void* psMetadataLookupPtr(
+psPtr psMetadataLookupPtr(
     psBool *status,                    ///< Status of lookup.
     psMetadata* md,                    ///< Metadata collection to lookup metadata item.
@@ -354,6 +426,53 @@
  */
 psMetadataItem* psMetadataGet(
-    psMetadata*  md,           ///< Metadata collection to insert metadat item.
-    psS32 where                ///< Location to be retrieved.
+    psMetadata*  md,                   ///< Metadata collection to insert metadat item.
+    psS32 location                     ///< Location to be retrieved.
+);
+
+/** Creates a psMetadataIterator to iterate over the specified psMetadata.
+ *
+ *  Supports the subsetting of the metadata via keyword using regular
+ *  expression.  If no regular expression is specified, iteration
+ *  over the entire psMetadata is performed.
+ *
+ *  @return psMetadataIterator*        a new psMetadataIterator, of NULL if error occurred
+ */
+psMetadataIterator* psMetadataIteratorAlloc(
+    psMetadata* md,                    ///< the psMetadata to iterate with
+    int location,                      ///< the initial starting point (after subsetting).
+    const char* regex
+    ///< A regular expression for subsetting the psMetadata.  If NULL, no
+    ///< subsetting is performed.
+);
+
+/** Set the iterator of the psMetadat to a given position.  If location is
+ *  invalid the iterator position is not changed.
+ *
+ *  @return psBool        TRUE if iterator successfully set, otherwise FALSE.
+*/
+psBool psMetadataIteratorSet(
+    psMetadataIterator* iterator,      ///< psMetadata iterator
+    int location                       ///< index number, PS_LIST_HEAD, or PS_LIST_TAIL
+);
+
+/** Position the specified iterator to the next matching item in psMetadata,
+ *  given the regular expression of the iterator
+ *
+ *  @return psPtr       the psMetadataItem at the original iterator position
+ *                      or NULL if the iterator went past the end of the list.
+ */
+psMetadataItem* psMetadataGetAndIncrement(
+    psMetadataIterator* iterator           ///< iterator to move
+);
+
+/** Position the specified iterator to the previous matching item in psMetadata,
+ *  given the regular expression of the iterator
+ *
+ *  @return psPtr       the psMetadataItem at the original iterator position
+ *                      or NULL if the iterator went past the beginning of the
+ *                      list.
+ */
+psMetadataItem* psMetadataGetAndDecrement(
+    psMetadataIterator* iterator           ///< iterator to move
 );
 
Index: /trunk/psLib/src/astronomy/psMetadataIO.c
===================================================================
--- /trunk/psLib/src/astronomy/psMetadataIO.c	(revision 3380)
+++ /trunk/psLib/src/astronomy/psMetadataIO.c	(revision 3381)
@@ -9,6 +9,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -410,18 +410,22 @@
         switch (keyType) {
         case 'I':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_S32,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_S32 | PS_META_DUPLICATE_OK,
                                     keyComment, atoi(keyValue));
             break;
         case 'F':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_F64,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_F64 | PS_META_DUPLICATE_OK,
                                     keyComment, atof(keyValue));
             break;
         case 'C':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_STR,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_STR | PS_META_DUPLICATE_OK,
                                     keyComment, keyValue);
             break;
         case 'L':
             tempBool = (keyValue[0] == 'T') ? 1 : 0;
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_BOOL,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_BOOL | PS_META_DUPLICATE_OK,
                                     keyComment, tempBool);
             break;
@@ -456,9 +460,9 @@
     psF64 tempDbl = 0.0;
     psS32 tempInt = 0.0;
-    psMetadataItem *metadataItem = NULL;
     psVector *tempVec = NULL;
     FILE *fp = NULL;
     psMetadataType mdType;
-
+    psMetadataFlags flags;
+    psBool addStatus;
 
     // Check for nulls
@@ -516,4 +520,6 @@
             }
 
+            flags = (overwrite) ? PS_META_REPLACE : PS_META_DEFAULT;
+
             // Get the metadata item type
             strType = getToken(&linePtr, " ", &status);
@@ -524,21 +530,27 @@
                         fileName);
                 continue;
-            } else if(!strncmp(strType, "*", 1)) {
-                mdType = PS_META_LIST;
-            } else if(!strncmp(strType, "STR", 3)) {
-                mdType = PS_META_STR;
-            } else if(!strncmp(strType, "BOOL", 4)) {
-                mdType = PS_META_BOOL;
-            } else if(!strncmp(strType, "S32", 3)) {
-                mdType = PS_META_S32;
-            } else if(!strncmp(strType, "F32", 3)) {
-                mdType = PS_META_F32;
-            } else if(!strncmp(strType, "F64", 3)) {
-                mdType = PS_META_F64;
             } else {
-                (*nFail)++;
-                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineCount,
-                        fileName);
-                continue;
+                char* tempStrType = strType;
+                if(*strType == '*') {
+                    flags = PS_META_DUPLICATE_OK;
+                    tempStrType = strType+1;
+                }
+
+                if(!strncmp(tempStrType, "STR", 3)) {
+                    mdType = PS_META_STR;
+                } else if(!strncmp(tempStrType, "BOOL", 4)) {
+                    mdType = PS_META_BOOL;
+                } else if(!strncmp(tempStrType, "S32", 3)) {
+                    mdType = PS_META_S32;
+                } else if(!strncmp(tempStrType, "F32", 3)) {
+                    mdType = PS_META_F32;
+                } else if(!strncmp(tempStrType, "F64", 3)) {
+                    mdType = PS_META_F64;
+                } else {
+                    (*nFail)++;
+                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineCount,
+                            fileName);
+                    continue;
+                }
             }
 
@@ -548,17 +560,22 @@
             }
 
-            // Get the metadata item value if there is one. Lines with * don't have values.
-            if(mdType != PS_META_LIST) {
-                strValue = getToken(&linePtr, "#", &status);
-                if(strValue==NULL) {
-                    (*nFail)++;
-                    status = 0;
-                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
-                            fileName);
-                    continue;
-                }
-            }
-
-            // Get the metadata item value if there is one. Not all lines will have comments, so NULL is ok.
+            // Get the metadata item value if there is one.
+            strValue = getToken(&linePtr, "#", &status);
+            if(status) {
+                (*nFail)++;
+                status = 0;
+                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "comment", lineCount,
+                        fileName);
+                continue;
+            }
+            if(strValue==NULL) {
+                (*nFail)++;
+                status = 0;
+                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
+                        fileName);
+                continue;
+            }
+
+            // Not all lines will have comments, so NULL is ok.
             strComment = getToken(&linePtr,"~", &status);
             if(status) {
@@ -570,33 +587,17 @@
             }
 
-            /* If metadata item is found, is not a folder node, and overwrite is allowed, then remove existing
-            and allow switch/case below to add new item. If overwrite is false, then report error. If found
-            item is folder node, then psMetadataAdd will automatically add a new child. */
-            metadataItem = psMetadataLookup(md, strName);
-            if(metadataItem != NULL) {
-                if(metadataItem->type!=PS_META_LIST) {
-                    if(overwrite) {
-                        psMetadataRemove(md, INT_MIN, strName);
-                    } else {
-                        (*nFail)++;
-                        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineCount,
-                                fileName);
-                        continue;
-                    }
-                }
-            }
-
             // Create and add metadata item to metadata and parse values
             switch (mdType) {
-            case PS_META_LIST:
-                psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, NULL);
-                break;
             case PS_META_STR:
-                psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, strValue);
+                addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                          mdType | flags,
+                                          strComment, strValue);
                 break;
             case PS_META_VEC:
                 tempVec = parseVector(strValue, vecType, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName+1, mdType, strComment, tempVec);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName+1,
+                                              mdType | flags,
+                                              strComment, tempVec);
                 } else {
                     status = 0;
@@ -611,5 +612,7 @@
                 tempBool = parseBool(strValue, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, tempBool);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                              mdType | flags,
+                                              strComment, tempBool);
                 } else {
                     status = 0;
@@ -623,5 +626,7 @@
                 tempInt = (psS32)parseValue(strValue, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, tempInt);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                              mdType | flags,
+                                              strComment, tempInt);
                 } else {
                     status = 0;
@@ -636,5 +641,7 @@
                 tempDbl = parseValue(strValue, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, tempDbl);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                              mdType | flags,
+                                              strComment, tempDbl);
                 } else {
                     status = 0;
@@ -652,4 +659,10 @@
                 continue;
             } // switch
+            if (! addStatus) {
+                (*nFail)++;
+                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineCount,
+                        fileName);
+            }
+
         } // if ignoreLine
     } // while loop
@@ -725,5 +738,7 @@
     // Add attributes to metadata
 
-    psMetadataAdd(md, PS_LIST_TAIL, "htAtts", PS_META_HASH, NULL, htAtts);
+    psMetadataAdd(md, PS_LIST_TAIL, "htAtts",
+                  PS_META_HASH | PS_META_DUPLICATE_OK,
+                  NULL, htAtts);
 
     psFree(psTagName);
@@ -828,13 +843,19 @@
     switch(mdType) {
     case PS_META_LIST:
-        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, NULL);
+        psMetadataAdd(md, PS_LIST_TAIL, strName,
+                      mdType | PS_META_DUPLICATE_OK,
+                      NULL, NULL);
         break;
     case PS_META_STR:
-        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, strValue);
+        psMetadataAdd(md, PS_LIST_TAIL, strName,
+                      mdType | PS_META_DUPLICATE_OK,
+                      NULL, strValue);
         break;
     case PS_META_BOOL:
         tempBool = parseBool((char*)strValue, &status);
         if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempBool);
+            psMetadataAdd(md, PS_LIST_TAIL, strName,
+                          mdType | PS_META_DUPLICATE_OK,
+                          NULL, tempBool);
         } else {
             status = 0;
@@ -846,5 +867,7 @@
         tempInt = (psS32)parseValue((char*)strValue, &status);
         if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempInt);
+            psMetadataAdd(md, PS_LIST_TAIL, strName,
+                          mdType | PS_META_DUPLICATE_OK,
+                          NULL, tempInt);
         } else {
             status = 0;
@@ -857,5 +880,7 @@
         tempDbl = parseValue((char*)strValue, &status);
         if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempDbl);
+            psMetadataAdd(md, PS_LIST_TAIL, strName,
+                          mdType | PS_META_DUPLICATE_OK,
+                          NULL, tempDbl);
         } else {
             status = 0;
@@ -966,5 +991,7 @@
     vec = parseVector((char*)strValue, pType, &status);
     if(!status) {
-        psMetadataAdd(md, PS_LIST_TAIL, strName+1, PS_META_VEC, NULL, vec);
+        psMetadataAdd(md, PS_LIST_TAIL, strName+1,
+                      PS_META_VEC | PS_META_DUPLICATE_OK,
+                      NULL, vec);
     } else {
         psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
Index: /trunk/psLib/src/astronomy/psMetadataIO.h
===================================================================
--- /trunk/psLib/src/astronomy/psMetadataIO.h	(revision 3380)
+++ /trunk/psLib/src/astronomy/psMetadataIO.h	(revision 3381)
@@ -1,20 +1,20 @@
 /** @file  psMetadataIO.h
-*
-*  @brief Contains metadata input/output functions.
-*
-*  This file defines functions to read and write metadata to/from an external file.
-*
-*  @ingroup Metadata
-*
-*  @author Ross Harman, MHPCC
-*
-*  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-17 19:26:23 $
-*
-*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
-*/
+ *
+ *  @brief Contains metadata input/output functions.
+ *
+ *  This file defines functions to read and write metadata to/from an external file.
+ *
+ *  @ingroup Metadata
+ *
+ *  @author Ross Harman, MHPCC
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-03-07 20:58:50 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
 #ifndef PS_METADATAIO_H
 #define PS_METADATAIO_H
-
 
 /// @addtogroup Metadata
Index: /trunk/psLib/src/collections/psList.h
===================================================================
--- /trunk/psLib/src/collections/psList.h	(revision 3380)
+++ /trunk/psLib/src/collections/psList.h	(revision 3381)
@@ -10,6 +10,6 @@
  *  @ingroup LinkedList
  *
- *  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-02-17 19:26:23 $
+ *  @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-03-07 20:58:50 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -174,6 +174,6 @@
 /** Position the specified iterator to the next item in list.
  *
- *  @return psPtr       the data item at the new iterator position or NULL if the
- *                      iterator goes past the end of the list.
+ *  @return psPtr       the data item at the original iterator position or NULL if the
+ *                      iterator went past the end of the list.
  */
 psPtr psListGetAndIncrement(
@@ -183,6 +183,6 @@
 /** Position the specified iterator to the previous item in list.
  *
- *  @return psPtr       the data item at the new iterator position or NULL if the
- *                      iterator goes past the beginning of the list.
+ *  @return psPtr       the data item at the original iterator position or NULL if the
+ *                      iterator went past the beginning of the list.
  */
 psPtr psListGetAndDecrement(
Index: /trunk/psLib/src/collections/psMetadata.c
===================================================================
--- /trunk/psLib/src/collections/psMetadata.c	(revision 3380)
+++ /trunk/psLib/src/collections/psMetadata.c	(revision 3381)
@@ -12,6 +12,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.53 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.54 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -85,4 +85,13 @@
 }
 
+static void metadataIteratorFree(psMetadataIterator* iter)
+{
+    if (iter == NULL) {
+        return;
+    }
+    psFree(iter->iter);
+    regfree(iter->preg);
+}
+
 static void metadataFree(psMetadata* metadata)
 {
@@ -158,5 +167,5 @@
 
     // Set metadata item type
-    metadataItem->type = type;
+    metadataItem->type = type & PS_METADATA_TYPE_MASK;
 
     // Allocate and set metadata item name
@@ -165,5 +174,5 @@
 
     // Set metadata item value
-    switch(type) {
+    switch(metadataItem->type) {
     case PS_META_BOOL:
         metadataItem->data.B = (psBool)va_arg(argPtr, psS32);
@@ -190,4 +199,5 @@
     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));
@@ -223,5 +233,5 @@
 }
 
-psBool psMetadataAddItem(psMetadata *md, psMetadataItem *metadataItem, psS32 location)
+psBool psMetadataAddItem(psMetadata *md, psMetadataItem *metadataItem, psS32 location, psS32 flags)
 {
     char * key = NULL;
@@ -229,6 +239,4 @@
     psList *mdList = NULL;
     psMetadataItem *existingEntry = NULL;
-    psMetadataItem *newFolderEntry = NULL;
-    psMetadataType newType;
 
     PS_PTR_CHECK_NULL(md,NULL);
@@ -238,5 +246,4 @@
     PS_PTR_CHECK_NULL(metadataItem->name,NULL);
 
-    newType = metadataItem->type;
     mdTable = md->table;
     mdList = md->list;
@@ -245,72 +252,56 @@
     // See if key is already in table
     existingEntry = (psMetadataItem*)psHashLookup(mdTable, key);
+
+    // how the item is added to the hash depends on flags & prior existence
     if(existingEntry != NULL) {
-
-        if(existingEntry->type == PS_META_LIST) {
-
-            if(existingEntry->data.list == NULL) {
-                existingEntry->data.list = psListAlloc(NULL);
+        if ((flags & PS_META_DUPLICATE_OK) != 0) {
+            // duplicate entries allowed - add another entry.
+            if (existingEntry->type != PS_META_MULTI) {
+                // first duplicate, transfer the hash's old entry into a
+                // list of entries with the type PS_META_MULTI.
+
+                // add entry to a list and dereference the local pointer
+                psList* newList = psListAlloc(existingEntry);
+
+                existingEntry = psMetadataItemAlloc(key,
+                                                    PS_META_MULTI,
+                                                    "",
+                                                    newList);
+                psHashRemove(mdTable,key); // take out the old entry
+                psHashAdd(mdTable, key, existingEntry); // put in the new entry
+
+                // free local references of newly allocated items.
+                psFree(newList);
+                psFree(existingEntry);
+
             }
 
-            // Add leaf node to existing folder node
-            if(!psListAdd(existingEntry->data.list, PS_LIST_TAIL, metadataItem)) {
-                psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_ADD_LIST_FAILED, metadataItem->name);
+            // 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(existingEntry->type != PS_META_LIST && newType!= PS_META_LIST) {
-
-            // Leaf node replaces another leaf. Make new folder node and add leaves.
-            newFolderEntry = psMetadataItemAlloc(key, PS_META_LIST, NULL, NULL);
-            newFolderEntry->data.list = psListAlloc(NULL);
-
-            if(!psListAdd(newFolderEntry->data.list, PS_LIST_TAIL, existingEntry)) {
-                psError(PS_ERR_UNKNOWN,false, PS_ERRORTEXT_psMetadata_ADD_LIST_FAILED,key);
-                psFree(newFolderEntry);
-                return false;
-            }
-
-            if(!psListAdd(newFolderEntry->data.list, PS_LIST_TAIL, metadataItem)) {
-                psError(PS_ERR_UNKNOWN,false, PS_ERRORTEXT_psMetadata_ADD_LIST_FAILED,key);
-                psFree(newFolderEntry);
-                return false;
-            }
-
-            if(!psHashRemove(mdTable, key)) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED,key);
-                psFree(newFolderEntry);
-                return false;
-            }
-
-            if(!psHashAdd(mdTable, key, newFolderEntry)) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
-                psFree(newFolderEntry);
-                return false;
-            }
-
-            // Remove local reference to new folder node
-            psMemDecrRefCounter(newFolderEntry);
-        } else {
-
-            // Folder node replaces leaf or folder node - Put old node into new folder and remove from table
-            if(metadataItem->data.list == NULL) {
-                metadataItem->data.list = psListAlloc(NULL);
-            }
-
-            if(!psListAdd(metadataItem->data.list, PS_LIST_TAIL, existingEntry)) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_LIST_FAILED,key);
-                return false;
-            }
-
-            if(!psHashRemove(mdTable, key)) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED,key);
-                return false;
-            }
-
+            // (added to list below)
+
+        } else if ((flags & PS_META_REPLACE) != 0) {
+            // replace entry instead of creating a duplicate entry.
+
+            // remove the existing entry from metadata
+            psListRemoveData(mdList, existingEntry);
+            psHashRemove(mdTable, 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
@@ -321,11 +312,7 @@
     }
 
-    // Add items to metadata collection's list, even if they have the same metadata item names. Folder nodes
-    // (PS_META_LIST metadata items) are not added, since the metadata list is flat.
-    if(metadataItem->type != PS_META_LIST) {
-        if(!psListAdd(mdList, location, metadataItem)) {
-            psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
-            return false;
-        }
+    if(!psListAdd(mdList, location, metadataItem)) {
+        psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
+        return false;
     }
 
@@ -333,15 +320,24 @@
 }
 
-psBool psMetadataAdd(psMetadata *md, psS32 where, const char *name,
-                     psMetadataType type, const char *comment, ...)
+psBool psMetadataAdd(psMetadata *md, psS32 location, const char *name,
+                     psS32 type, const char *comment, ...)
 {
     va_list argPtr;
+
+    va_start(argPtr, comment);
+    psBool result = psMetadataAddV(md,location,name,type,comment,argPtr);
+    va_end(argPtr);
+
+    return result;
+}
+
+psBool psMetadataAddV(psMetadata *md, psS32 location, const char *name,
+                      psS32 type, const char *comment, va_list list)
+{
     psMetadataItem* metadataItem = NULL;
 
-    va_start(argPtr, comment);
-    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
-    va_end(argPtr);
-
-    if (!psMetadataAddItem(md, metadataItem, where)) {
+    metadataItem = psMetadataItemAllocV(name, type & PS_METADATA_TYPE_MASK, comment, list);
+
+    if (!psMetadataAddItem(md, metadataItem, location, type & PS_METADATA_FLAGS_MASK)) {
         psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_FAILED);
         psFree(metadataItem);
@@ -373,51 +369,72 @@
 psBool psMetadataRemove(psMetadata *md, psS32 where, const char *key)
 {
-    psList* mdList = NULL;
-    psHash* mdTable = NULL;
-    psMetadataItem* entry = NULL;
-
-
     PS_PTR_CHECK_NULL(md,NULL);
+
+    PS_PTR_CHECK_NULL(md->list,NULL);
+    psList* mdList = md->list;
+
     PS_PTR_CHECK_NULL(md->table,NULL);
-    PS_PTR_CHECK_NULL(md->list,NULL);
-
-    mdList = md->list;
-    mdTable = md->table;
+    psHash* mdTable = md->table;
 
     // Select removal by key or index
     if (key != NULL) {
-
         // Remove by key name
-        entry = (psMetadataItem*)psHashLookup(mdTable, key);
+        psMetadataItem* entry = psHashLookup(mdTable,key);
         if (entry == NULL) {
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_FIND_FAILED, key);
+            psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
             return false;
         }
-
+        if (entry->type == PS_META_MULTI) {
+            psMetadataItem* listItem;
+            psListIterator* iter = psListIteratorAlloc(
+                                       entry->data.list,
+                                       PS_LIST_HEAD,true);
+            while ((listItem=psListGetAndIncrement(iter)) != NULL) {
+                psListRemoveData(mdList, listItem);
+            }
+            psFree(iter);
+            psHashRemove(mdTable,key);
+
+        } else {
+            psListRemoveData(mdList, entry);
+            psHashRemove(mdTable, key);
+        }
     } else {
-
         // Remove by index
-        entry = psListGet(mdList, where);
+        psMetadataItem* entry = psListGet(mdList, where);
         if (entry == NULL) {
             psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_FIND_INDEX_FAILED, where);
             return false;
         }
-
         key = entry->name;
-        if(key == NULL) {
+
+        if (key == NULL) {
             psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_REMOVE_LIST_INDEX_FAILED, where);
             return false;
         }
-    }
-
-    if (!psListRemoveData(mdList, entry)) {
-        psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_LIST_FAILED, key);
-        return false;
-    }
-
-    // Remove entry from metadata collection's table
-    if (!psHashRemove(mdTable, key)) {
-        psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
-        return false;
+
+        psMetadataItem* tableItem = psHashLookup(mdTable, key);
+        if (tableItem == NULL) {
+            psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
+            return false;
+        }
+
+        if (tableItem->type == PS_META_MULTI) {
+            // multiple entries with same key, remove just the specified one
+            psListRemoveData(tableItem->data.list, entry);
+            if (psListGet(tableItem->data.list,PS_LIST_HEAD) == NULL) {
+                // list is empty, so let's clear the whole entry now.
+                if (!psHashRemove(mdTable, key)) {
+                    psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
+                    return false;
+                }
+            }
+        } else {
+            if (!psHashRemove(mdTable, key)) {
+                psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
+                return false;
+            }
+        }
+        psListRemove(mdList, where);
     }
 
@@ -455,4 +472,8 @@
         }
         return NULL;
+    }
+    if (metadataItem->type == PS_META_MULTI) {
+        // if multiple keys found, use the first.
+        metadataItem = (psMetadataItem*)((metadataItem->data.list)->head);
     }
 
@@ -486,4 +507,8 @@
         } \
         return 0; \
+    } \
+    if (metadataItem->type == PS_META_MULTI) { \
+        /* if multiple keys found, use the first. */ \
+        metadataItem = (psMetadataItem*)((metadataItem->data.list)->head); \
     } \
     \
@@ -535,2 +560,145 @@
     return entry;
 }
+
+psMetadataIterator* psMetadataIteratorAlloc(psMetadata* md,
+        int location,
+        const char* regex)
+{
+    PS_PTR_CHECK_NULL(md,NULL);
+    PS_PTR_CHECK_NULL(md->list,NULL);
+
+    psMetadataIterator* newIter = psAlloc(sizeof(psMetadataIterator));
+    newIter->preg = NULL;
+    newIter->iter = NULL;
+
+    // Set deallocator
+    p_psMemSetDeallocator(newIter, (psFreeFcn) metadataIteratorFree);
+
+    if (regex == NULL) {
+        newIter->iter = psListIteratorAlloc(md->list, location, false);
+        return newIter;
+    } else {
+        int regRtn = regcomp(newIter->preg,regex,0);
+        if (regRtn != 0) {
+            char errMsg[256];
+            regerror(regRtn, newIter->preg, errMsg, 256);
+            regfree(newIter->preg);
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    PS_ERRORTEXT_psMetadata_REGEX_INVALID,
+                    errMsg);
+            psFree(newIter);
+            return NULL;
+        }
+    }
+
+    psMetadataIteratorSet(newIter, location); // XXX: do we error if no match is found?
+
+    return newIter;
+}
+
+psBool psMetadataIteratorSet(psMetadataIterator* iterator,
+                             int location)
+{
+    int match;
+    psMetadataItem* cursor;
+
+    PS_PTR_CHECK_NULL(iterator,NULL);
+
+    psListIterator* iter = iterator->iter;
+    PS_PTR_CHECK_NULL(iterator->iter,NULL);
+
+    regex_t* preg = iterator->preg;
+
+    // handle trivial case where no regex subsetting is required.
+    if (preg == NULL) {
+        return psListIteratorSet(iter,location);
+    }
+
+    if (location < 0) {
+        // match from the tail
+        match = 0;
+        psListIteratorSet(iter,PS_LIST_TAIL);
+        while ( (cursor=(psMetadataItem*)iter->cursor) != NULL) {
+            if (regexec(preg, cursor->name, 0, NULL, 0) == 0) {
+                // this key is a match
+                match--;
+                if (match == location) {
+                    break;
+                }
+            }
+            (void)psListGetAndDecrement(iter);
+        }
+        return (match == location);
+    }
+
+    // find the n-th match from the head
+    match = -1;
+    psListIteratorSet(iter,PS_LIST_HEAD);
+    while ( (cursor=(psMetadataItem*)iter->cursor) != NULL) {
+        if (regexec(preg, cursor->name, 0, NULL, 0) == 0) {
+            // this key is a match
+            match++;
+            if (match == location) {
+                break;
+            }
+        }
+        (void)psListGetAndIncrement(iter);
+    }
+    return (match == location);
+}
+
+psMetadataItem* psMetadataGetAndIncrement(psMetadataIterator* iterator)
+{
+    psMetadataItem* oldValue;
+
+    PS_PTR_CHECK_NULL(iterator,NULL);
+
+    psListIterator* iter = iterator->iter;
+    PS_PTR_CHECK_NULL(iterator->iter,NULL);
+
+    regex_t* preg = iterator->preg;
+
+    // handle trivial case where no regex subsetting is required.
+    if (preg == NULL) {
+        return (psMetadataItem*)psListGetAndIncrement(iter);
+    }
+
+    oldValue = (psMetadataItem*)iter->cursor;
+
+    while (psListGetAndIncrement(iter) != NULL) {
+        if (iter->cursor != NULL &&
+                regexec(preg, ((psMetadataItem*)iter->cursor)->name, 0, NULL, 0) == 0) {
+            // this key is a match
+            break;
+        }
+    }
+    return oldValue;
+}
+
+psMetadataItem* psMetadataGetAndDecrement(psMetadataIterator* iterator)
+{
+    psMetadataItem* oldValue;
+
+    PS_PTR_CHECK_NULL(iterator,NULL);
+
+    psListIterator* iter = iterator->iter;
+    PS_PTR_CHECK_NULL(iterator->iter,NULL);
+
+    regex_t* preg = iterator->preg;
+
+    // handle trivial case where no regex subsetting is required.
+    if (preg == NULL) {
+        return (psMetadataItem*)psListGetAndDecrement(iter);
+    }
+
+    oldValue = (psMetadataItem*)iter->cursor;
+
+    while (psListGetAndDecrement(iter) != NULL) {
+        if (iter->cursor != NULL &&
+                regexec(preg, ((psMetadataItem*)iter->cursor)->name, 0, NULL, 0) == 0) {
+            // this key is a match
+            break;
+        }
+    }
+    return oldValue;
+}
Index: /trunk/psLib/src/collections/psMetadata.h
===================================================================
--- /trunk/psLib/src/collections/psMetadata.h	(revision 3380)
+++ /trunk/psLib/src/collections/psMetadata.h	(revision 3381)
@@ -11,6 +11,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.38 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.39 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -21,4 +21,6 @@
 #include <stdarg.h>
 #include <stdio.h>
+#include <sys/types.h>
+#include <regex.h>
 
 #include "psHash.h"
@@ -35,8 +37,8 @@
  */
 typedef enum {
-    PS_META_S32,                       ///< Primitive data.
-    PS_META_F32,                       ///< Primitive data.
-    PS_META_F64,                       ///< Primitive data.
-    PS_META_BOOL,                       ///< Primitive data.
+    PS_META_S32,                       ///< psS32 primitive data.
+    PS_META_F32,                       ///< psF32 primitive data.
+    PS_META_F64,                       ///< psF64 primitive data.
+    PS_META_BOOL,                      ///< psBool primitive data.
     PS_META_LIST,                      ///< List data (Stored as item.data.list).
     PS_META_STR,                       ///< String data (Stored as item.data.V).
@@ -49,4 +51,5 @@
     PS_META_ASTROM,                    ///< Astrometric coefficients (Stored as item.data.V).
     PS_META_UNKNOWN,                   ///< Other data (Stored as item.data.V).
+    PS_META_MULTI,                     ///< Used internally, do not create an metadata item of this type.
     PS_META_NTYPE                      ///< Number of types. Must be last.
 } psMetadataType;
@@ -72,6 +75,10 @@
 typedef enum {
     PS_META_DEFAULT = 0,               ///< default behaviour (duplicate entry is an error)
-    PS_META_REPLACE = 0x10000          ///< allow entry to be replaced
+    PS_META_REPLACE = 0x1000000,       ///< allow entry to be replaced
+    PS_META_DUPLICATE_OK = 0x2000000   ///< allow duplicate entries
 } psMetadataFlags;
+
+#define PS_METADATA_FLAGS_MASK 0xFF000000
+#define PS_METADATA_TYPE_MASK 0x00FFFFFF
 
 /** Metadata data structure.
@@ -88,4 +95,16 @@
 }
 psMetadata;
+
+/** Metadata iterator
+ *
+ *  Iterator for metadata.
+ */
+typedef struct
+{
+    psListIterator* iter;              ///< iterator for the psMetadata's psList
+    regex_t* preg;                     ///< the subsetting regular expression
+}
+psMetadataIterator;
+
 
 /** Metadata item data structure.
@@ -134,32 +153,67 @@
 );
 
+/** Create a metadata item with specified string data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocStr(
-    const char* name,
-    const char* comment,
-    const char* value
-);
-
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    const char* value                  ///< the value of the metadata item.
+);
+
+/** Create a metadata item with specified psF32 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocF32(
-    const char* name,
-    const char* comment,
-    psF32 value
-);
-
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psF32 value                        ///< the value of the metadata item.
+);
+
+/** Create a metadata item with specified psF64 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocF64(
-    const char* name,
-    const char* comment,
-    psF64 value
-);
-
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psF64 value                        ///< the value of the metadata item.
+);
+
+/** Create a metadata item with specified psS32 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocS32(
-    const char* name,
-    const char* comment,
-    psS32 value
-);
-
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psS32 value                        ///< the value of the metadata item.
+);
+
+/** Create a metadata item with specified psBool data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocBool(
-    const char* name,
-    const char* comment,
-    psBool value
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psBool value                       ///< the value of the metadata item.
 );
 
@@ -207,5 +261,6 @@
     psMetadata*  md,                   ///< Metadata collection to insert metadat item.
     psMetadataItem*  item,             ///< Metadata item to be added.
-    psS32 location                     ///< Location to be added.
+    psS32 location,                    ///< Location to be added.
+    psS32 flags                        ///< Options flag mask, see psMetadataFlags enum
 );
 
@@ -218,30 +273,47 @@
 psBool psMetadataAdd(
     psMetadata* md,                    ///< Metadata collection to insert metadat item.
-    psS32 where,                       ///< Location to be added.
+    psS32 location,                    ///< Location to be added.
     const char *name,                  ///< Name of metadata item.
-    psMetadataType type,               ///< Type of metadata item.
+    int type,                          ///< Type of metadata item (psMetadataType) and options (psMetadataFlags)
     const char *comment,               ///< Comment for metadata item.
     ...                                ///< Arguments for name formatting and metadata item data.
 );
 
-psBool psMetadataAddS32(psMetadata* md, psS32 where, const char* name,
+#ifndef SWIG
+/** Create and add a metadata item to metadata collection.
+ *
+ * Creates a new metadata item add to the metadata collection.
+ *
+ * @return bool: True for success, false for failure.
+ */
+psBool psMetadataAddV(
+    psMetadata* md,                    ///< Metadata collection to insert metadat item.
+    psS32 location,                    ///< Location to be added.
+    const char *name,                  ///< Name of metadata item.
+    int type,                          ///< Type of metadata item (psMetadataType) and options (psMetadataFlags)
+    const char *comment,               ///< Comment for metadata item.
+    va_list list                       ///< Arguments for name formatting and metadata item data.
+);
+#endif
+
+psBool psMetadataAddS32(psMetadata* md, psS32 location, const char* name,
                         const char* comment, psS32 value);
-psBool psMetadataAddF32(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddF32(psMetadata* md, psS32 location, const char* name,
                         const char* comment, psF32 value);
-psBool psMetadataAddF64(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddF64(psMetadata* md, psS32 location, const char* name,
                         const char* comment, psF64 value);
-psBool psMetadataAddList(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddList(psMetadata* md, psS32 location, const char* name,
                          const char* comment, psList* value);
-psBool psMetadataAddStr(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddStr(psMetadata* md, psS32 location, const char* name,
                         const char* comment, const char* value);
-psBool psMetadataAddVector(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddVector(psMetadata* md, psS32 location, const char* name,
                            const char* comment, psVector* value);
-psBool psMetadataAddImage(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddImage(psMetadata* md, psS32 location, const char* name,
                           const char* comment, psImage* value);
-psBool psMetadataAddHash(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddHash(psMetadata* md, psS32 location, const char* name,
                          const char* comment, psHash* value);
-psBool psMetadataAddLookupTable(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddLookupTable(psMetadata* md, psS32 location, const char* name,
                                 const char* comment, psLookupTable* value);
-psBool psMetadataAddUnknown(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddUnknown(psMetadata* md, psS32 location, const char* name,
                             const char* comment, psPtr value);
 
@@ -340,5 +412,5 @@
  * @return void* : Value of metadata item.
  */
-void* psMetadataLookupPtr(
+psPtr psMetadataLookupPtr(
     psBool *status,                    ///< Status of lookup.
     psMetadata* md,                    ///< Metadata collection to lookup metadata item.
@@ -354,6 +426,53 @@
  */
 psMetadataItem* psMetadataGet(
-    psMetadata*  md,           ///< Metadata collection to insert metadat item.
-    psS32 where                ///< Location to be retrieved.
+    psMetadata*  md,                   ///< Metadata collection to insert metadat item.
+    psS32 location                     ///< Location to be retrieved.
+);
+
+/** Creates a psMetadataIterator to iterate over the specified psMetadata.
+ *
+ *  Supports the subsetting of the metadata via keyword using regular
+ *  expression.  If no regular expression is specified, iteration
+ *  over the entire psMetadata is performed.
+ *
+ *  @return psMetadataIterator*        a new psMetadataIterator, of NULL if error occurred
+ */
+psMetadataIterator* psMetadataIteratorAlloc(
+    psMetadata* md,                    ///< the psMetadata to iterate with
+    int location,                      ///< the initial starting point (after subsetting).
+    const char* regex
+    ///< A regular expression for subsetting the psMetadata.  If NULL, no
+    ///< subsetting is performed.
+);
+
+/** Set the iterator of the psMetadat to a given position.  If location is
+ *  invalid the iterator position is not changed.
+ *
+ *  @return psBool        TRUE if iterator successfully set, otherwise FALSE.
+*/
+psBool psMetadataIteratorSet(
+    psMetadataIterator* iterator,      ///< psMetadata iterator
+    int location                       ///< index number, PS_LIST_HEAD, or PS_LIST_TAIL
+);
+
+/** Position the specified iterator to the next matching item in psMetadata,
+ *  given the regular expression of the iterator
+ *
+ *  @return psPtr       the psMetadataItem at the original iterator position
+ *                      or NULL if the iterator went past the end of the list.
+ */
+psMetadataItem* psMetadataGetAndIncrement(
+    psMetadataIterator* iterator           ///< iterator to move
+);
+
+/** Position the specified iterator to the previous matching item in psMetadata,
+ *  given the regular expression of the iterator
+ *
+ *  @return psPtr       the psMetadataItem at the original iterator position
+ *                      or NULL if the iterator went past the beginning of the
+ *                      list.
+ */
+psMetadataItem* psMetadataGetAndDecrement(
+    psMetadataIterator* iterator           ///< iterator to move
 );
 
Index: /trunk/psLib/src/collections/psMetadataIO.c
===================================================================
--- /trunk/psLib/src/collections/psMetadataIO.c	(revision 3380)
+++ /trunk/psLib/src/collections/psMetadataIO.c	(revision 3381)
@@ -9,6 +9,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -410,18 +410,22 @@
         switch (keyType) {
         case 'I':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_S32,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_S32 | PS_META_DUPLICATE_OK,
                                     keyComment, atoi(keyValue));
             break;
         case 'F':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_F64,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_F64 | PS_META_DUPLICATE_OK,
                                     keyComment, atof(keyValue));
             break;
         case 'C':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_STR,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_STR | PS_META_DUPLICATE_OK,
                                     keyComment, keyValue);
             break;
         case 'L':
             tempBool = (keyValue[0] == 'T') ? 1 : 0;
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_BOOL,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_BOOL | PS_META_DUPLICATE_OK,
                                     keyComment, tempBool);
             break;
@@ -456,9 +460,9 @@
     psF64 tempDbl = 0.0;
     psS32 tempInt = 0.0;
-    psMetadataItem *metadataItem = NULL;
     psVector *tempVec = NULL;
     FILE *fp = NULL;
     psMetadataType mdType;
-
+    psMetadataFlags flags;
+    psBool addStatus;
 
     // Check for nulls
@@ -516,4 +520,6 @@
             }
 
+            flags = (overwrite) ? PS_META_REPLACE : PS_META_DEFAULT;
+
             // Get the metadata item type
             strType = getToken(&linePtr, " ", &status);
@@ -524,21 +530,27 @@
                         fileName);
                 continue;
-            } else if(!strncmp(strType, "*", 1)) {
-                mdType = PS_META_LIST;
-            } else if(!strncmp(strType, "STR", 3)) {
-                mdType = PS_META_STR;
-            } else if(!strncmp(strType, "BOOL", 4)) {
-                mdType = PS_META_BOOL;
-            } else if(!strncmp(strType, "S32", 3)) {
-                mdType = PS_META_S32;
-            } else if(!strncmp(strType, "F32", 3)) {
-                mdType = PS_META_F32;
-            } else if(!strncmp(strType, "F64", 3)) {
-                mdType = PS_META_F64;
             } else {
-                (*nFail)++;
-                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineCount,
-                        fileName);
-                continue;
+                char* tempStrType = strType;
+                if(*strType == '*') {
+                    flags = PS_META_DUPLICATE_OK;
+                    tempStrType = strType+1;
+                }
+
+                if(!strncmp(tempStrType, "STR", 3)) {
+                    mdType = PS_META_STR;
+                } else if(!strncmp(tempStrType, "BOOL", 4)) {
+                    mdType = PS_META_BOOL;
+                } else if(!strncmp(tempStrType, "S32", 3)) {
+                    mdType = PS_META_S32;
+                } else if(!strncmp(tempStrType, "F32", 3)) {
+                    mdType = PS_META_F32;
+                } else if(!strncmp(tempStrType, "F64", 3)) {
+                    mdType = PS_META_F64;
+                } else {
+                    (*nFail)++;
+                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineCount,
+                            fileName);
+                    continue;
+                }
             }
 
@@ -548,17 +560,22 @@
             }
 
-            // Get the metadata item value if there is one. Lines with * don't have values.
-            if(mdType != PS_META_LIST) {
-                strValue = getToken(&linePtr, "#", &status);
-                if(strValue==NULL) {
-                    (*nFail)++;
-                    status = 0;
-                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
-                            fileName);
-                    continue;
-                }
-            }
-
-            // Get the metadata item value if there is one. Not all lines will have comments, so NULL is ok.
+            // Get the metadata item value if there is one.
+            strValue = getToken(&linePtr, "#", &status);
+            if(status) {
+                (*nFail)++;
+                status = 0;
+                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "comment", lineCount,
+                        fileName);
+                continue;
+            }
+            if(strValue==NULL) {
+                (*nFail)++;
+                status = 0;
+                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
+                        fileName);
+                continue;
+            }
+
+            // Not all lines will have comments, so NULL is ok.
             strComment = getToken(&linePtr,"~", &status);
             if(status) {
@@ -570,33 +587,17 @@
             }
 
-            /* If metadata item is found, is not a folder node, and overwrite is allowed, then remove existing
-            and allow switch/case below to add new item. If overwrite is false, then report error. If found
-            item is folder node, then psMetadataAdd will automatically add a new child. */
-            metadataItem = psMetadataLookup(md, strName);
-            if(metadataItem != NULL) {
-                if(metadataItem->type!=PS_META_LIST) {
-                    if(overwrite) {
-                        psMetadataRemove(md, INT_MIN, strName);
-                    } else {
-                        (*nFail)++;
-                        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineCount,
-                                fileName);
-                        continue;
-                    }
-                }
-            }
-
             // Create and add metadata item to metadata and parse values
             switch (mdType) {
-            case PS_META_LIST:
-                psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, NULL);
-                break;
             case PS_META_STR:
-                psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, strValue);
+                addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                          mdType | flags,
+                                          strComment, strValue);
                 break;
             case PS_META_VEC:
                 tempVec = parseVector(strValue, vecType, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName+1, mdType, strComment, tempVec);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName+1,
+                                              mdType | flags,
+                                              strComment, tempVec);
                 } else {
                     status = 0;
@@ -611,5 +612,7 @@
                 tempBool = parseBool(strValue, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, tempBool);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                              mdType | flags,
+                                              strComment, tempBool);
                 } else {
                     status = 0;
@@ -623,5 +626,7 @@
                 tempInt = (psS32)parseValue(strValue, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, tempInt);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                              mdType | flags,
+                                              strComment, tempInt);
                 } else {
                     status = 0;
@@ -636,5 +641,7 @@
                 tempDbl = parseValue(strValue, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, tempDbl);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                              mdType | flags,
+                                              strComment, tempDbl);
                 } else {
                     status = 0;
@@ -652,4 +659,10 @@
                 continue;
             } // switch
+            if (! addStatus) {
+                (*nFail)++;
+                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineCount,
+                        fileName);
+            }
+
         } // if ignoreLine
     } // while loop
@@ -725,5 +738,7 @@
     // Add attributes to metadata
 
-    psMetadataAdd(md, PS_LIST_TAIL, "htAtts", PS_META_HASH, NULL, htAtts);
+    psMetadataAdd(md, PS_LIST_TAIL, "htAtts",
+                  PS_META_HASH | PS_META_DUPLICATE_OK,
+                  NULL, htAtts);
 
     psFree(psTagName);
@@ -828,13 +843,19 @@
     switch(mdType) {
     case PS_META_LIST:
-        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, NULL);
+        psMetadataAdd(md, PS_LIST_TAIL, strName,
+                      mdType | PS_META_DUPLICATE_OK,
+                      NULL, NULL);
         break;
     case PS_META_STR:
-        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, strValue);
+        psMetadataAdd(md, PS_LIST_TAIL, strName,
+                      mdType | PS_META_DUPLICATE_OK,
+                      NULL, strValue);
         break;
     case PS_META_BOOL:
         tempBool = parseBool((char*)strValue, &status);
         if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempBool);
+            psMetadataAdd(md, PS_LIST_TAIL, strName,
+                          mdType | PS_META_DUPLICATE_OK,
+                          NULL, tempBool);
         } else {
             status = 0;
@@ -846,5 +867,7 @@
         tempInt = (psS32)parseValue((char*)strValue, &status);
         if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempInt);
+            psMetadataAdd(md, PS_LIST_TAIL, strName,
+                          mdType | PS_META_DUPLICATE_OK,
+                          NULL, tempInt);
         } else {
             status = 0;
@@ -857,5 +880,7 @@
         tempDbl = parseValue((char*)strValue, &status);
         if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempDbl);
+            psMetadataAdd(md, PS_LIST_TAIL, strName,
+                          mdType | PS_META_DUPLICATE_OK,
+                          NULL, tempDbl);
         } else {
             status = 0;
@@ -966,5 +991,7 @@
     vec = parseVector((char*)strValue, pType, &status);
     if(!status) {
-        psMetadataAdd(md, PS_LIST_TAIL, strName+1, PS_META_VEC, NULL, vec);
+        psMetadataAdd(md, PS_LIST_TAIL, strName+1,
+                      PS_META_VEC | PS_META_DUPLICATE_OK,
+                      NULL, vec);
     } else {
         psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
Index: /trunk/psLib/src/collections/psMetadataIO.h
===================================================================
--- /trunk/psLib/src/collections/psMetadataIO.h	(revision 3380)
+++ /trunk/psLib/src/collections/psMetadataIO.h	(revision 3381)
@@ -1,20 +1,20 @@
 /** @file  psMetadataIO.h
-*
-*  @brief Contains metadata input/output functions.
-*
-*  This file defines functions to read and write metadata to/from an external file.
-*
-*  @ingroup Metadata
-*
-*  @author Ross Harman, MHPCC
-*
-*  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-17 19:26:23 $
-*
-*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
-*/
+ *
+ *  @brief Contains metadata input/output functions.
+ *
+ *  This file defines functions to read and write metadata to/from an external file.
+ *
+ *  @ingroup Metadata
+ *
+ *  @author Ross Harman, MHPCC
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-03-07 20:58:50 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
 #ifndef PS_METADATAIO_H
 #define PS_METADATAIO_H
-
 
 /// @addtogroup Metadata
Index: /trunk/psLib/src/sys/psType.h
===================================================================
--- /trunk/psLib/src/sys/psType.h	(revision 3380)
+++ /trunk/psLib/src/sys/psType.h	(revision 3381)
@@ -10,6 +10,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.30 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.31 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -50,4 +50,5 @@
 typedef float psF32;                   ///< 32-bit floating point
 typedef double psF64;                  ///< 64-bit floating point
+
 #ifdef SWIG
 typedef struct
@@ -65,4 +66,5 @@
 typedef double _Complex psC64;         ///< complex with 64-bit floating point Real and Imagary numbers
 #endif
+
 typedef void* psPtr;                   ///< void pointer
 typedef bool psBool;                   ///< boolean value
@@ -204,5 +206,5 @@
 #define PS_IS_PSELEMTYPE_BOOL(x) ((x & 0x1000) == 0x1000)
 /// Macro to determine the storage size, in bytes, of the psElemType.
-#define PSELEMTYPE_SIZEOF(x) ( (x==PS_TYPE_PTR) ? sizeof(psPtr) :(x & 0xFF) )
+#define PSELEMTYPE_SIZEOF(x) ( (x==(PS_TYPE_PTR&0xFFFF)) ? sizeof(psPtr) :(x & 0xFF) )
 
 /** Dimensions of a data type.
Index: /trunk/psLib/src/sysUtils/psType.h
===================================================================
--- /trunk/psLib/src/sysUtils/psType.h	(revision 3380)
+++ /trunk/psLib/src/sysUtils/psType.h	(revision 3381)
@@ -10,6 +10,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.30 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.31 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -50,4 +50,5 @@
 typedef float psF32;                   ///< 32-bit floating point
 typedef double psF64;                  ///< 64-bit floating point
+
 #ifdef SWIG
 typedef struct
@@ -65,4 +66,5 @@
 typedef double _Complex psC64;         ///< complex with 64-bit floating point Real and Imagary numbers
 #endif
+
 typedef void* psPtr;                   ///< void pointer
 typedef bool psBool;                   ///< boolean value
@@ -204,5 +206,5 @@
 #define PS_IS_PSELEMTYPE_BOOL(x) ((x & 0x1000) == 0x1000)
 /// Macro to determine the storage size, in bytes, of the psElemType.
-#define PSELEMTYPE_SIZEOF(x) ( (x==PS_TYPE_PTR) ? sizeof(psPtr) :(x & 0xFF) )
+#define PSELEMTYPE_SIZEOF(x) ( (x==(PS_TYPE_PTR&0xFFFF)) ? sizeof(psPtr) :(x & 0xFF) )
 
 /** Dimensions of a data type.
Index: /trunk/psLib/src/types/psList.h
===================================================================
--- /trunk/psLib/src/types/psList.h	(revision 3380)
+++ /trunk/psLib/src/types/psList.h	(revision 3381)
@@ -10,6 +10,6 @@
  *  @ingroup LinkedList
  *
- *  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-02-17 19:26:23 $
+ *  @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-03-07 20:58:50 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -174,6 +174,6 @@
 /** Position the specified iterator to the next item in list.
  *
- *  @return psPtr       the data item at the new iterator position or NULL if the
- *                      iterator goes past the end of the list.
+ *  @return psPtr       the data item at the original iterator position or NULL if the
+ *                      iterator went past the end of the list.
  */
 psPtr psListGetAndIncrement(
@@ -183,6 +183,6 @@
 /** Position the specified iterator to the previous item in list.
  *
- *  @return psPtr       the data item at the new iterator position or NULL if the
- *                      iterator goes past the beginning of the list.
+ *  @return psPtr       the data item at the original iterator position or NULL if the
+ *                      iterator went past the beginning of the list.
  */
 psPtr psListGetAndDecrement(
Index: /trunk/psLib/src/types/psMetadata.c
===================================================================
--- /trunk/psLib/src/types/psMetadata.c	(revision 3380)
+++ /trunk/psLib/src/types/psMetadata.c	(revision 3381)
@@ -12,6 +12,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.53 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.54 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -85,4 +85,13 @@
 }
 
+static void metadataIteratorFree(psMetadataIterator* iter)
+{
+    if (iter == NULL) {
+        return;
+    }
+    psFree(iter->iter);
+    regfree(iter->preg);
+}
+
 static void metadataFree(psMetadata* metadata)
 {
@@ -158,5 +167,5 @@
 
     // Set metadata item type
-    metadataItem->type = type;
+    metadataItem->type = type & PS_METADATA_TYPE_MASK;
 
     // Allocate and set metadata item name
@@ -165,5 +174,5 @@
 
     // Set metadata item value
-    switch(type) {
+    switch(metadataItem->type) {
     case PS_META_BOOL:
         metadataItem->data.B = (psBool)va_arg(argPtr, psS32);
@@ -190,4 +199,5 @@
     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));
@@ -223,5 +233,5 @@
 }
 
-psBool psMetadataAddItem(psMetadata *md, psMetadataItem *metadataItem, psS32 location)
+psBool psMetadataAddItem(psMetadata *md, psMetadataItem *metadataItem, psS32 location, psS32 flags)
 {
     char * key = NULL;
@@ -229,6 +239,4 @@
     psList *mdList = NULL;
     psMetadataItem *existingEntry = NULL;
-    psMetadataItem *newFolderEntry = NULL;
-    psMetadataType newType;
 
     PS_PTR_CHECK_NULL(md,NULL);
@@ -238,5 +246,4 @@
     PS_PTR_CHECK_NULL(metadataItem->name,NULL);
 
-    newType = metadataItem->type;
     mdTable = md->table;
     mdList = md->list;
@@ -245,72 +252,56 @@
     // See if key is already in table
     existingEntry = (psMetadataItem*)psHashLookup(mdTable, key);
+
+    // how the item is added to the hash depends on flags & prior existence
     if(existingEntry != NULL) {
-
-        if(existingEntry->type == PS_META_LIST) {
-
-            if(existingEntry->data.list == NULL) {
-                existingEntry->data.list = psListAlloc(NULL);
+        if ((flags & PS_META_DUPLICATE_OK) != 0) {
+            // duplicate entries allowed - add another entry.
+            if (existingEntry->type != PS_META_MULTI) {
+                // first duplicate, transfer the hash's old entry into a
+                // list of entries with the type PS_META_MULTI.
+
+                // add entry to a list and dereference the local pointer
+                psList* newList = psListAlloc(existingEntry);
+
+                existingEntry = psMetadataItemAlloc(key,
+                                                    PS_META_MULTI,
+                                                    "",
+                                                    newList);
+                psHashRemove(mdTable,key); // take out the old entry
+                psHashAdd(mdTable, key, existingEntry); // put in the new entry
+
+                // free local references of newly allocated items.
+                psFree(newList);
+                psFree(existingEntry);
+
             }
 
-            // Add leaf node to existing folder node
-            if(!psListAdd(existingEntry->data.list, PS_LIST_TAIL, metadataItem)) {
-                psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_ADD_LIST_FAILED, metadataItem->name);
+            // 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(existingEntry->type != PS_META_LIST && newType!= PS_META_LIST) {
-
-            // Leaf node replaces another leaf. Make new folder node and add leaves.
-            newFolderEntry = psMetadataItemAlloc(key, PS_META_LIST, NULL, NULL);
-            newFolderEntry->data.list = psListAlloc(NULL);
-
-            if(!psListAdd(newFolderEntry->data.list, PS_LIST_TAIL, existingEntry)) {
-                psError(PS_ERR_UNKNOWN,false, PS_ERRORTEXT_psMetadata_ADD_LIST_FAILED,key);
-                psFree(newFolderEntry);
-                return false;
-            }
-
-            if(!psListAdd(newFolderEntry->data.list, PS_LIST_TAIL, metadataItem)) {
-                psError(PS_ERR_UNKNOWN,false, PS_ERRORTEXT_psMetadata_ADD_LIST_FAILED,key);
-                psFree(newFolderEntry);
-                return false;
-            }
-
-            if(!psHashRemove(mdTable, key)) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED,key);
-                psFree(newFolderEntry);
-                return false;
-            }
-
-            if(!psHashAdd(mdTable, key, newFolderEntry)) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
-                psFree(newFolderEntry);
-                return false;
-            }
-
-            // Remove local reference to new folder node
-            psMemDecrRefCounter(newFolderEntry);
-        } else {
-
-            // Folder node replaces leaf or folder node - Put old node into new folder and remove from table
-            if(metadataItem->data.list == NULL) {
-                metadataItem->data.list = psListAlloc(NULL);
-            }
-
-            if(!psListAdd(metadataItem->data.list, PS_LIST_TAIL, existingEntry)) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_LIST_FAILED,key);
-                return false;
-            }
-
-            if(!psHashRemove(mdTable, key)) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED,key);
-                return false;
-            }
-
+            // (added to list below)
+
+        } else if ((flags & PS_META_REPLACE) != 0) {
+            // replace entry instead of creating a duplicate entry.
+
+            // remove the existing entry from metadata
+            psListRemoveData(mdList, existingEntry);
+            psHashRemove(mdTable, 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
@@ -321,11 +312,7 @@
     }
 
-    // Add items to metadata collection's list, even if they have the same metadata item names. Folder nodes
-    // (PS_META_LIST metadata items) are not added, since the metadata list is flat.
-    if(metadataItem->type != PS_META_LIST) {
-        if(!psListAdd(mdList, location, metadataItem)) {
-            psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
-            return false;
-        }
+    if(!psListAdd(mdList, location, metadataItem)) {
+        psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
+        return false;
     }
 
@@ -333,15 +320,24 @@
 }
 
-psBool psMetadataAdd(psMetadata *md, psS32 where, const char *name,
-                     psMetadataType type, const char *comment, ...)
+psBool psMetadataAdd(psMetadata *md, psS32 location, const char *name,
+                     psS32 type, const char *comment, ...)
 {
     va_list argPtr;
+
+    va_start(argPtr, comment);
+    psBool result = psMetadataAddV(md,location,name,type,comment,argPtr);
+    va_end(argPtr);
+
+    return result;
+}
+
+psBool psMetadataAddV(psMetadata *md, psS32 location, const char *name,
+                      psS32 type, const char *comment, va_list list)
+{
     psMetadataItem* metadataItem = NULL;
 
-    va_start(argPtr, comment);
-    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
-    va_end(argPtr);
-
-    if (!psMetadataAddItem(md, metadataItem, where)) {
+    metadataItem = psMetadataItemAllocV(name, type & PS_METADATA_TYPE_MASK, comment, list);
+
+    if (!psMetadataAddItem(md, metadataItem, location, type & PS_METADATA_FLAGS_MASK)) {
         psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_FAILED);
         psFree(metadataItem);
@@ -373,51 +369,72 @@
 psBool psMetadataRemove(psMetadata *md, psS32 where, const char *key)
 {
-    psList* mdList = NULL;
-    psHash* mdTable = NULL;
-    psMetadataItem* entry = NULL;
-
-
     PS_PTR_CHECK_NULL(md,NULL);
+
+    PS_PTR_CHECK_NULL(md->list,NULL);
+    psList* mdList = md->list;
+
     PS_PTR_CHECK_NULL(md->table,NULL);
-    PS_PTR_CHECK_NULL(md->list,NULL);
-
-    mdList = md->list;
-    mdTable = md->table;
+    psHash* mdTable = md->table;
 
     // Select removal by key or index
     if (key != NULL) {
-
         // Remove by key name
-        entry = (psMetadataItem*)psHashLookup(mdTable, key);
+        psMetadataItem* entry = psHashLookup(mdTable,key);
         if (entry == NULL) {
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_FIND_FAILED, key);
+            psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
             return false;
         }
-
+        if (entry->type == PS_META_MULTI) {
+            psMetadataItem* listItem;
+            psListIterator* iter = psListIteratorAlloc(
+                                       entry->data.list,
+                                       PS_LIST_HEAD,true);
+            while ((listItem=psListGetAndIncrement(iter)) != NULL) {
+                psListRemoveData(mdList, listItem);
+            }
+            psFree(iter);
+            psHashRemove(mdTable,key);
+
+        } else {
+            psListRemoveData(mdList, entry);
+            psHashRemove(mdTable, key);
+        }
     } else {
-
         // Remove by index
-        entry = psListGet(mdList, where);
+        psMetadataItem* entry = psListGet(mdList, where);
         if (entry == NULL) {
             psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_FIND_INDEX_FAILED, where);
             return false;
         }
-
         key = entry->name;
-        if(key == NULL) {
+
+        if (key == NULL) {
             psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_REMOVE_LIST_INDEX_FAILED, where);
             return false;
         }
-    }
-
-    if (!psListRemoveData(mdList, entry)) {
-        psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_LIST_FAILED, key);
-        return false;
-    }
-
-    // Remove entry from metadata collection's table
-    if (!psHashRemove(mdTable, key)) {
-        psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
-        return false;
+
+        psMetadataItem* tableItem = psHashLookup(mdTable, key);
+        if (tableItem == NULL) {
+            psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
+            return false;
+        }
+
+        if (tableItem->type == PS_META_MULTI) {
+            // multiple entries with same key, remove just the specified one
+            psListRemoveData(tableItem->data.list, entry);
+            if (psListGet(tableItem->data.list,PS_LIST_HEAD) == NULL) {
+                // list is empty, so let's clear the whole entry now.
+                if (!psHashRemove(mdTable, key)) {
+                    psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
+                    return false;
+                }
+            }
+        } else {
+            if (!psHashRemove(mdTable, key)) {
+                psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
+                return false;
+            }
+        }
+        psListRemove(mdList, where);
     }
 
@@ -455,4 +472,8 @@
         }
         return NULL;
+    }
+    if (metadataItem->type == PS_META_MULTI) {
+        // if multiple keys found, use the first.
+        metadataItem = (psMetadataItem*)((metadataItem->data.list)->head);
     }
 
@@ -486,4 +507,8 @@
         } \
         return 0; \
+    } \
+    if (metadataItem->type == PS_META_MULTI) { \
+        /* if multiple keys found, use the first. */ \
+        metadataItem = (psMetadataItem*)((metadataItem->data.list)->head); \
     } \
     \
@@ -535,2 +560,145 @@
     return entry;
 }
+
+psMetadataIterator* psMetadataIteratorAlloc(psMetadata* md,
+        int location,
+        const char* regex)
+{
+    PS_PTR_CHECK_NULL(md,NULL);
+    PS_PTR_CHECK_NULL(md->list,NULL);
+
+    psMetadataIterator* newIter = psAlloc(sizeof(psMetadataIterator));
+    newIter->preg = NULL;
+    newIter->iter = NULL;
+
+    // Set deallocator
+    p_psMemSetDeallocator(newIter, (psFreeFcn) metadataIteratorFree);
+
+    if (regex == NULL) {
+        newIter->iter = psListIteratorAlloc(md->list, location, false);
+        return newIter;
+    } else {
+        int regRtn = regcomp(newIter->preg,regex,0);
+        if (regRtn != 0) {
+            char errMsg[256];
+            regerror(regRtn, newIter->preg, errMsg, 256);
+            regfree(newIter->preg);
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    PS_ERRORTEXT_psMetadata_REGEX_INVALID,
+                    errMsg);
+            psFree(newIter);
+            return NULL;
+        }
+    }
+
+    psMetadataIteratorSet(newIter, location); // XXX: do we error if no match is found?
+
+    return newIter;
+}
+
+psBool psMetadataIteratorSet(psMetadataIterator* iterator,
+                             int location)
+{
+    int match;
+    psMetadataItem* cursor;
+
+    PS_PTR_CHECK_NULL(iterator,NULL);
+
+    psListIterator* iter = iterator->iter;
+    PS_PTR_CHECK_NULL(iterator->iter,NULL);
+
+    regex_t* preg = iterator->preg;
+
+    // handle trivial case where no regex subsetting is required.
+    if (preg == NULL) {
+        return psListIteratorSet(iter,location);
+    }
+
+    if (location < 0) {
+        // match from the tail
+        match = 0;
+        psListIteratorSet(iter,PS_LIST_TAIL);
+        while ( (cursor=(psMetadataItem*)iter->cursor) != NULL) {
+            if (regexec(preg, cursor->name, 0, NULL, 0) == 0) {
+                // this key is a match
+                match--;
+                if (match == location) {
+                    break;
+                }
+            }
+            (void)psListGetAndDecrement(iter);
+        }
+        return (match == location);
+    }
+
+    // find the n-th match from the head
+    match = -1;
+    psListIteratorSet(iter,PS_LIST_HEAD);
+    while ( (cursor=(psMetadataItem*)iter->cursor) != NULL) {
+        if (regexec(preg, cursor->name, 0, NULL, 0) == 0) {
+            // this key is a match
+            match++;
+            if (match == location) {
+                break;
+            }
+        }
+        (void)psListGetAndIncrement(iter);
+    }
+    return (match == location);
+}
+
+psMetadataItem* psMetadataGetAndIncrement(psMetadataIterator* iterator)
+{
+    psMetadataItem* oldValue;
+
+    PS_PTR_CHECK_NULL(iterator,NULL);
+
+    psListIterator* iter = iterator->iter;
+    PS_PTR_CHECK_NULL(iterator->iter,NULL);
+
+    regex_t* preg = iterator->preg;
+
+    // handle trivial case where no regex subsetting is required.
+    if (preg == NULL) {
+        return (psMetadataItem*)psListGetAndIncrement(iter);
+    }
+
+    oldValue = (psMetadataItem*)iter->cursor;
+
+    while (psListGetAndIncrement(iter) != NULL) {
+        if (iter->cursor != NULL &&
+                regexec(preg, ((psMetadataItem*)iter->cursor)->name, 0, NULL, 0) == 0) {
+            // this key is a match
+            break;
+        }
+    }
+    return oldValue;
+}
+
+psMetadataItem* psMetadataGetAndDecrement(psMetadataIterator* iterator)
+{
+    psMetadataItem* oldValue;
+
+    PS_PTR_CHECK_NULL(iterator,NULL);
+
+    psListIterator* iter = iterator->iter;
+    PS_PTR_CHECK_NULL(iterator->iter,NULL);
+
+    regex_t* preg = iterator->preg;
+
+    // handle trivial case where no regex subsetting is required.
+    if (preg == NULL) {
+        return (psMetadataItem*)psListGetAndDecrement(iter);
+    }
+
+    oldValue = (psMetadataItem*)iter->cursor;
+
+    while (psListGetAndDecrement(iter) != NULL) {
+        if (iter->cursor != NULL &&
+                regexec(preg, ((psMetadataItem*)iter->cursor)->name, 0, NULL, 0) == 0) {
+            // this key is a match
+            break;
+        }
+    }
+    return oldValue;
+}
Index: /trunk/psLib/src/types/psMetadata.h
===================================================================
--- /trunk/psLib/src/types/psMetadata.h	(revision 3380)
+++ /trunk/psLib/src/types/psMetadata.h	(revision 3381)
@@ -11,6 +11,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.38 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.39 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -21,4 +21,6 @@
 #include <stdarg.h>
 #include <stdio.h>
+#include <sys/types.h>
+#include <regex.h>
 
 #include "psHash.h"
@@ -35,8 +37,8 @@
  */
 typedef enum {
-    PS_META_S32,                       ///< Primitive data.
-    PS_META_F32,                       ///< Primitive data.
-    PS_META_F64,                       ///< Primitive data.
-    PS_META_BOOL,                       ///< Primitive data.
+    PS_META_S32,                       ///< psS32 primitive data.
+    PS_META_F32,                       ///< psF32 primitive data.
+    PS_META_F64,                       ///< psF64 primitive data.
+    PS_META_BOOL,                      ///< psBool primitive data.
     PS_META_LIST,                      ///< List data (Stored as item.data.list).
     PS_META_STR,                       ///< String data (Stored as item.data.V).
@@ -49,4 +51,5 @@
     PS_META_ASTROM,                    ///< Astrometric coefficients (Stored as item.data.V).
     PS_META_UNKNOWN,                   ///< Other data (Stored as item.data.V).
+    PS_META_MULTI,                     ///< Used internally, do not create an metadata item of this type.
     PS_META_NTYPE                      ///< Number of types. Must be last.
 } psMetadataType;
@@ -72,6 +75,10 @@
 typedef enum {
     PS_META_DEFAULT = 0,               ///< default behaviour (duplicate entry is an error)
-    PS_META_REPLACE = 0x10000          ///< allow entry to be replaced
+    PS_META_REPLACE = 0x1000000,       ///< allow entry to be replaced
+    PS_META_DUPLICATE_OK = 0x2000000   ///< allow duplicate entries
 } psMetadataFlags;
+
+#define PS_METADATA_FLAGS_MASK 0xFF000000
+#define PS_METADATA_TYPE_MASK 0x00FFFFFF
 
 /** Metadata data structure.
@@ -88,4 +95,16 @@
 }
 psMetadata;
+
+/** Metadata iterator
+ *
+ *  Iterator for metadata.
+ */
+typedef struct
+{
+    psListIterator* iter;              ///< iterator for the psMetadata's psList
+    regex_t* preg;                     ///< the subsetting regular expression
+}
+psMetadataIterator;
+
 
 /** Metadata item data structure.
@@ -134,32 +153,67 @@
 );
 
+/** Create a metadata item with specified string data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocStr(
-    const char* name,
-    const char* comment,
-    const char* value
-);
-
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    const char* value                  ///< the value of the metadata item.
+);
+
+/** Create a metadata item with specified psF32 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocF32(
-    const char* name,
-    const char* comment,
-    psF32 value
-);
-
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psF32 value                        ///< the value of the metadata item.
+);
+
+/** Create a metadata item with specified psF64 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocF64(
-    const char* name,
-    const char* comment,
-    psF64 value
-);
-
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psF64 value                        ///< the value of the metadata item.
+);
+
+/** Create a metadata item with specified psS32 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocS32(
-    const char* name,
-    const char* comment,
-    psS32 value
-);
-
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psS32 value                        ///< the value of the metadata item.
+);
+
+/** Create a metadata item with specified psBool data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
 psMetadataItem* psMetadataItemAllocBool(
-    const char* name,
-    const char* comment,
-    psBool value
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psBool value                       ///< the value of the metadata item.
 );
 
@@ -207,5 +261,6 @@
     psMetadata*  md,                   ///< Metadata collection to insert metadat item.
     psMetadataItem*  item,             ///< Metadata item to be added.
-    psS32 location                     ///< Location to be added.
+    psS32 location,                    ///< Location to be added.
+    psS32 flags                        ///< Options flag mask, see psMetadataFlags enum
 );
 
@@ -218,30 +273,47 @@
 psBool psMetadataAdd(
     psMetadata* md,                    ///< Metadata collection to insert metadat item.
-    psS32 where,                       ///< Location to be added.
+    psS32 location,                    ///< Location to be added.
     const char *name,                  ///< Name of metadata item.
-    psMetadataType type,               ///< Type of metadata item.
+    int type,                          ///< Type of metadata item (psMetadataType) and options (psMetadataFlags)
     const char *comment,               ///< Comment for metadata item.
     ...                                ///< Arguments for name formatting and metadata item data.
 );
 
-psBool psMetadataAddS32(psMetadata* md, psS32 where, const char* name,
+#ifndef SWIG
+/** Create and add a metadata item to metadata collection.
+ *
+ * Creates a new metadata item add to the metadata collection.
+ *
+ * @return bool: True for success, false for failure.
+ */
+psBool psMetadataAddV(
+    psMetadata* md,                    ///< Metadata collection to insert metadat item.
+    psS32 location,                    ///< Location to be added.
+    const char *name,                  ///< Name of metadata item.
+    int type,                          ///< Type of metadata item (psMetadataType) and options (psMetadataFlags)
+    const char *comment,               ///< Comment for metadata item.
+    va_list list                       ///< Arguments for name formatting and metadata item data.
+);
+#endif
+
+psBool psMetadataAddS32(psMetadata* md, psS32 location, const char* name,
                         const char* comment, psS32 value);
-psBool psMetadataAddF32(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddF32(psMetadata* md, psS32 location, const char* name,
                         const char* comment, psF32 value);
-psBool psMetadataAddF64(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddF64(psMetadata* md, psS32 location, const char* name,
                         const char* comment, psF64 value);
-psBool psMetadataAddList(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddList(psMetadata* md, psS32 location, const char* name,
                          const char* comment, psList* value);
-psBool psMetadataAddStr(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddStr(psMetadata* md, psS32 location, const char* name,
                         const char* comment, const char* value);
-psBool psMetadataAddVector(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddVector(psMetadata* md, psS32 location, const char* name,
                            const char* comment, psVector* value);
-psBool psMetadataAddImage(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddImage(psMetadata* md, psS32 location, const char* name,
                           const char* comment, psImage* value);
-psBool psMetadataAddHash(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddHash(psMetadata* md, psS32 location, const char* name,
                          const char* comment, psHash* value);
-psBool psMetadataAddLookupTable(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddLookupTable(psMetadata* md, psS32 location, const char* name,
                                 const char* comment, psLookupTable* value);
-psBool psMetadataAddUnknown(psMetadata* md, psS32 where, const char* name,
+psBool psMetadataAddUnknown(psMetadata* md, psS32 location, const char* name,
                             const char* comment, psPtr value);
 
@@ -340,5 +412,5 @@
  * @return void* : Value of metadata item.
  */
-void* psMetadataLookupPtr(
+psPtr psMetadataLookupPtr(
     psBool *status,                    ///< Status of lookup.
     psMetadata* md,                    ///< Metadata collection to lookup metadata item.
@@ -354,6 +426,53 @@
  */
 psMetadataItem* psMetadataGet(
-    psMetadata*  md,           ///< Metadata collection to insert metadat item.
-    psS32 where                ///< Location to be retrieved.
+    psMetadata*  md,                   ///< Metadata collection to insert metadat item.
+    psS32 location                     ///< Location to be retrieved.
+);
+
+/** Creates a psMetadataIterator to iterate over the specified psMetadata.
+ *
+ *  Supports the subsetting of the metadata via keyword using regular
+ *  expression.  If no regular expression is specified, iteration
+ *  over the entire psMetadata is performed.
+ *
+ *  @return psMetadataIterator*        a new psMetadataIterator, of NULL if error occurred
+ */
+psMetadataIterator* psMetadataIteratorAlloc(
+    psMetadata* md,                    ///< the psMetadata to iterate with
+    int location,                      ///< the initial starting point (after subsetting).
+    const char* regex
+    ///< A regular expression for subsetting the psMetadata.  If NULL, no
+    ///< subsetting is performed.
+);
+
+/** Set the iterator of the psMetadat to a given position.  If location is
+ *  invalid the iterator position is not changed.
+ *
+ *  @return psBool        TRUE if iterator successfully set, otherwise FALSE.
+*/
+psBool psMetadataIteratorSet(
+    psMetadataIterator* iterator,      ///< psMetadata iterator
+    int location                       ///< index number, PS_LIST_HEAD, or PS_LIST_TAIL
+);
+
+/** Position the specified iterator to the next matching item in psMetadata,
+ *  given the regular expression of the iterator
+ *
+ *  @return psPtr       the psMetadataItem at the original iterator position
+ *                      or NULL if the iterator went past the end of the list.
+ */
+psMetadataItem* psMetadataGetAndIncrement(
+    psMetadataIterator* iterator           ///< iterator to move
+);
+
+/** Position the specified iterator to the previous matching item in psMetadata,
+ *  given the regular expression of the iterator
+ *
+ *  @return psPtr       the psMetadataItem at the original iterator position
+ *                      or NULL if the iterator went past the beginning of the
+ *                      list.
+ */
+psMetadataItem* psMetadataGetAndDecrement(
+    psMetadataIterator* iterator           ///< iterator to move
 );
 
Index: /trunk/psLib/src/types/psMetadataConfig.c
===================================================================
--- /trunk/psLib/src/types/psMetadataConfig.c	(revision 3380)
+++ /trunk/psLib/src/types/psMetadataConfig.c	(revision 3381)
@@ -9,6 +9,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -410,18 +410,22 @@
         switch (keyType) {
         case 'I':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_S32,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_S32 | PS_META_DUPLICATE_OK,
                                     keyComment, atoi(keyValue));
             break;
         case 'F':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_F64,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_F64 | PS_META_DUPLICATE_OK,
                                     keyComment, atof(keyValue));
             break;
         case 'C':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_STR,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_STR | PS_META_DUPLICATE_OK,
                                     keyComment, keyValue);
             break;
         case 'L':
             tempBool = (keyValue[0] == 'T') ? 1 : 0;
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_BOOL,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_BOOL | PS_META_DUPLICATE_OK,
                                     keyComment, tempBool);
             break;
@@ -456,9 +460,9 @@
     psF64 tempDbl = 0.0;
     psS32 tempInt = 0.0;
-    psMetadataItem *metadataItem = NULL;
     psVector *tempVec = NULL;
     FILE *fp = NULL;
     psMetadataType mdType;
-
+    psMetadataFlags flags;
+    psBool addStatus;
 
     // Check for nulls
@@ -516,4 +520,6 @@
             }
 
+            flags = (overwrite) ? PS_META_REPLACE : PS_META_DEFAULT;
+
             // Get the metadata item type
             strType = getToken(&linePtr, " ", &status);
@@ -524,21 +530,27 @@
                         fileName);
                 continue;
-            } else if(!strncmp(strType, "*", 1)) {
-                mdType = PS_META_LIST;
-            } else if(!strncmp(strType, "STR", 3)) {
-                mdType = PS_META_STR;
-            } else if(!strncmp(strType, "BOOL", 4)) {
-                mdType = PS_META_BOOL;
-            } else if(!strncmp(strType, "S32", 3)) {
-                mdType = PS_META_S32;
-            } else if(!strncmp(strType, "F32", 3)) {
-                mdType = PS_META_F32;
-            } else if(!strncmp(strType, "F64", 3)) {
-                mdType = PS_META_F64;
             } else {
-                (*nFail)++;
-                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineCount,
-                        fileName);
-                continue;
+                char* tempStrType = strType;
+                if(*strType == '*') {
+                    flags = PS_META_DUPLICATE_OK;
+                    tempStrType = strType+1;
+                }
+
+                if(!strncmp(tempStrType, "STR", 3)) {
+                    mdType = PS_META_STR;
+                } else if(!strncmp(tempStrType, "BOOL", 4)) {
+                    mdType = PS_META_BOOL;
+                } else if(!strncmp(tempStrType, "S32", 3)) {
+                    mdType = PS_META_S32;
+                } else if(!strncmp(tempStrType, "F32", 3)) {
+                    mdType = PS_META_F32;
+                } else if(!strncmp(tempStrType, "F64", 3)) {
+                    mdType = PS_META_F64;
+                } else {
+                    (*nFail)++;
+                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineCount,
+                            fileName);
+                    continue;
+                }
             }
 
@@ -548,17 +560,22 @@
             }
 
-            // Get the metadata item value if there is one. Lines with * don't have values.
-            if(mdType != PS_META_LIST) {
-                strValue = getToken(&linePtr, "#", &status);
-                if(strValue==NULL) {
-                    (*nFail)++;
-                    status = 0;
-                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
-                            fileName);
-                    continue;
-                }
-            }
-
-            // Get the metadata item value if there is one. Not all lines will have comments, so NULL is ok.
+            // Get the metadata item value if there is one.
+            strValue = getToken(&linePtr, "#", &status);
+            if(status) {
+                (*nFail)++;
+                status = 0;
+                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "comment", lineCount,
+                        fileName);
+                continue;
+            }
+            if(strValue==NULL) {
+                (*nFail)++;
+                status = 0;
+                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
+                        fileName);
+                continue;
+            }
+
+            // Not all lines will have comments, so NULL is ok.
             strComment = getToken(&linePtr,"~", &status);
             if(status) {
@@ -570,33 +587,17 @@
             }
 
-            /* If metadata item is found, is not a folder node, and overwrite is allowed, then remove existing
-            and allow switch/case below to add new item. If overwrite is false, then report error. If found
-            item is folder node, then psMetadataAdd will automatically add a new child. */
-            metadataItem = psMetadataLookup(md, strName);
-            if(metadataItem != NULL) {
-                if(metadataItem->type!=PS_META_LIST) {
-                    if(overwrite) {
-                        psMetadataRemove(md, INT_MIN, strName);
-                    } else {
-                        (*nFail)++;
-                        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineCount,
-                                fileName);
-                        continue;
-                    }
-                }
-            }
-
             // Create and add metadata item to metadata and parse values
             switch (mdType) {
-            case PS_META_LIST:
-                psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, NULL);
-                break;
             case PS_META_STR:
-                psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, strValue);
+                addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                          mdType | flags,
+                                          strComment, strValue);
                 break;
             case PS_META_VEC:
                 tempVec = parseVector(strValue, vecType, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName+1, mdType, strComment, tempVec);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName+1,
+                                              mdType | flags,
+                                              strComment, tempVec);
                 } else {
                     status = 0;
@@ -611,5 +612,7 @@
                 tempBool = parseBool(strValue, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, tempBool);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                              mdType | flags,
+                                              strComment, tempBool);
                 } else {
                     status = 0;
@@ -623,5 +626,7 @@
                 tempInt = (psS32)parseValue(strValue, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, tempInt);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                              mdType | flags,
+                                              strComment, tempInt);
                 } else {
                     status = 0;
@@ -636,5 +641,7 @@
                 tempDbl = parseValue(strValue, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, tempDbl);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                              mdType | flags,
+                                              strComment, tempDbl);
                 } else {
                     status = 0;
@@ -652,4 +659,10 @@
                 continue;
             } // switch
+            if (! addStatus) {
+                (*nFail)++;
+                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineCount,
+                        fileName);
+            }
+
         } // if ignoreLine
     } // while loop
@@ -725,5 +738,7 @@
     // Add attributes to metadata
 
-    psMetadataAdd(md, PS_LIST_TAIL, "htAtts", PS_META_HASH, NULL, htAtts);
+    psMetadataAdd(md, PS_LIST_TAIL, "htAtts",
+                  PS_META_HASH | PS_META_DUPLICATE_OK,
+                  NULL, htAtts);
 
     psFree(psTagName);
@@ -828,13 +843,19 @@
     switch(mdType) {
     case PS_META_LIST:
-        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, NULL);
+        psMetadataAdd(md, PS_LIST_TAIL, strName,
+                      mdType | PS_META_DUPLICATE_OK,
+                      NULL, NULL);
         break;
     case PS_META_STR:
-        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, strValue);
+        psMetadataAdd(md, PS_LIST_TAIL, strName,
+                      mdType | PS_META_DUPLICATE_OK,
+                      NULL, strValue);
         break;
     case PS_META_BOOL:
         tempBool = parseBool((char*)strValue, &status);
         if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempBool);
+            psMetadataAdd(md, PS_LIST_TAIL, strName,
+                          mdType | PS_META_DUPLICATE_OK,
+                          NULL, tempBool);
         } else {
             status = 0;
@@ -846,5 +867,7 @@
         tempInt = (psS32)parseValue((char*)strValue, &status);
         if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempInt);
+            psMetadataAdd(md, PS_LIST_TAIL, strName,
+                          mdType | PS_META_DUPLICATE_OK,
+                          NULL, tempInt);
         } else {
             status = 0;
@@ -857,5 +880,7 @@
         tempDbl = parseValue((char*)strValue, &status);
         if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempDbl);
+            psMetadataAdd(md, PS_LIST_TAIL, strName,
+                          mdType | PS_META_DUPLICATE_OK,
+                          NULL, tempDbl);
         } else {
             status = 0;
@@ -966,5 +991,7 @@
     vec = parseVector((char*)strValue, pType, &status);
     if(!status) {
-        psMetadataAdd(md, PS_LIST_TAIL, strName+1, PS_META_VEC, NULL, vec);
+        psMetadataAdd(md, PS_LIST_TAIL, strName+1,
+                      PS_META_VEC | PS_META_DUPLICATE_OK,
+                      NULL, vec);
     } else {
         psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
Index: /trunk/psLib/src/types/psMetadataConfig.h
===================================================================
--- /trunk/psLib/src/types/psMetadataConfig.h	(revision 3380)
+++ /trunk/psLib/src/types/psMetadataConfig.h	(revision 3381)
@@ -1,20 +1,20 @@
 /** @file  psMetadataIO.h
-*
-*  @brief Contains metadata input/output functions.
-*
-*  This file defines functions to read and write metadata to/from an external file.
-*
-*  @ingroup Metadata
-*
-*  @author Ross Harman, MHPCC
-*
-*  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-17 19:26:23 $
-*
-*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
-*/
+ *
+ *  @brief Contains metadata input/output functions.
+ *
+ *  This file defines functions to read and write metadata to/from an external file.
+ *
+ *  @ingroup Metadata
+ *
+ *  @author Ross Harman, MHPCC
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-03-07 20:58:50 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
 #ifndef PS_METADATAIO_H
 #define PS_METADATAIO_H
-
 
 /// @addtogroup Metadata
Index: /trunk/psLib/src/xml/psXML.c
===================================================================
--- /trunk/psLib/src/xml/psXML.c	(revision 3380)
+++ /trunk/psLib/src/xml/psXML.c	(revision 3381)
@@ -9,6 +9,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -410,18 +410,22 @@
         switch (keyType) {
         case 'I':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_S32,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_S32 | PS_META_DUPLICATE_OK,
                                     keyComment, atoi(keyValue));
             break;
         case 'F':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_F64,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_F64 | PS_META_DUPLICATE_OK,
                                     keyComment, atof(keyValue));
             break;
         case 'C':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_STR,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_STR | PS_META_DUPLICATE_OK,
                                     keyComment, keyValue);
             break;
         case 'L':
             tempBool = (keyValue[0] == 'T') ? 1 : 0;
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName, PS_META_BOOL,
+            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
+                                    PS_META_BOOL | PS_META_DUPLICATE_OK,
                                     keyComment, tempBool);
             break;
@@ -456,9 +460,9 @@
     psF64 tempDbl = 0.0;
     psS32 tempInt = 0.0;
-    psMetadataItem *metadataItem = NULL;
     psVector *tempVec = NULL;
     FILE *fp = NULL;
     psMetadataType mdType;
-
+    psMetadataFlags flags;
+    psBool addStatus;
 
     // Check for nulls
@@ -516,4 +520,6 @@
             }
 
+            flags = (overwrite) ? PS_META_REPLACE : PS_META_DEFAULT;
+
             // Get the metadata item type
             strType = getToken(&linePtr, " ", &status);
@@ -524,21 +530,27 @@
                         fileName);
                 continue;
-            } else if(!strncmp(strType, "*", 1)) {
-                mdType = PS_META_LIST;
-            } else if(!strncmp(strType, "STR", 3)) {
-                mdType = PS_META_STR;
-            } else if(!strncmp(strType, "BOOL", 4)) {
-                mdType = PS_META_BOOL;
-            } else if(!strncmp(strType, "S32", 3)) {
-                mdType = PS_META_S32;
-            } else if(!strncmp(strType, "F32", 3)) {
-                mdType = PS_META_F32;
-            } else if(!strncmp(strType, "F64", 3)) {
-                mdType = PS_META_F64;
             } else {
-                (*nFail)++;
-                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineCount,
-                        fileName);
-                continue;
+                char* tempStrType = strType;
+                if(*strType == '*') {
+                    flags = PS_META_DUPLICATE_OK;
+                    tempStrType = strType+1;
+                }
+
+                if(!strncmp(tempStrType, "STR", 3)) {
+                    mdType = PS_META_STR;
+                } else if(!strncmp(tempStrType, "BOOL", 4)) {
+                    mdType = PS_META_BOOL;
+                } else if(!strncmp(tempStrType, "S32", 3)) {
+                    mdType = PS_META_S32;
+                } else if(!strncmp(tempStrType, "F32", 3)) {
+                    mdType = PS_META_F32;
+                } else if(!strncmp(tempStrType, "F64", 3)) {
+                    mdType = PS_META_F64;
+                } else {
+                    (*nFail)++;
+                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineCount,
+                            fileName);
+                    continue;
+                }
             }
 
@@ -548,17 +560,22 @@
             }
 
-            // Get the metadata item value if there is one. Lines with * don't have values.
-            if(mdType != PS_META_LIST) {
-                strValue = getToken(&linePtr, "#", &status);
-                if(strValue==NULL) {
-                    (*nFail)++;
-                    status = 0;
-                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
-                            fileName);
-                    continue;
-                }
-            }
-
-            // Get the metadata item value if there is one. Not all lines will have comments, so NULL is ok.
+            // Get the metadata item value if there is one.
+            strValue = getToken(&linePtr, "#", &status);
+            if(status) {
+                (*nFail)++;
+                status = 0;
+                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "comment", lineCount,
+                        fileName);
+                continue;
+            }
+            if(strValue==NULL) {
+                (*nFail)++;
+                status = 0;
+                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
+                        fileName);
+                continue;
+            }
+
+            // Not all lines will have comments, so NULL is ok.
             strComment = getToken(&linePtr,"~", &status);
             if(status) {
@@ -570,33 +587,17 @@
             }
 
-            /* If metadata item is found, is not a folder node, and overwrite is allowed, then remove existing
-            and allow switch/case below to add new item. If overwrite is false, then report error. If found
-            item is folder node, then psMetadataAdd will automatically add a new child. */
-            metadataItem = psMetadataLookup(md, strName);
-            if(metadataItem != NULL) {
-                if(metadataItem->type!=PS_META_LIST) {
-                    if(overwrite) {
-                        psMetadataRemove(md, INT_MIN, strName);
-                    } else {
-                        (*nFail)++;
-                        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineCount,
-                                fileName);
-                        continue;
-                    }
-                }
-            }
-
             // Create and add metadata item to metadata and parse values
             switch (mdType) {
-            case PS_META_LIST:
-                psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, NULL);
-                break;
             case PS_META_STR:
-                psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, strValue);
+                addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                          mdType | flags,
+                                          strComment, strValue);
                 break;
             case PS_META_VEC:
                 tempVec = parseVector(strValue, vecType, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName+1, mdType, strComment, tempVec);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName+1,
+                                              mdType | flags,
+                                              strComment, tempVec);
                 } else {
                     status = 0;
@@ -611,5 +612,7 @@
                 tempBool = parseBool(strValue, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, tempBool);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                              mdType | flags,
+                                              strComment, tempBool);
                 } else {
                     status = 0;
@@ -623,5 +626,7 @@
                 tempInt = (psS32)parseValue(strValue, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, tempInt);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                              mdType | flags,
+                                              strComment, tempInt);
                 } else {
                     status = 0;
@@ -636,5 +641,7 @@
                 tempDbl = parseValue(strValue, &status);
                 if(!status) {
-                    psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, strComment, tempDbl);
+                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
+                                              mdType | flags,
+                                              strComment, tempDbl);
                 } else {
                     status = 0;
@@ -652,4 +659,10 @@
                 continue;
             } // switch
+            if (! addStatus) {
+                (*nFail)++;
+                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineCount,
+                        fileName);
+            }
+
         } // if ignoreLine
     } // while loop
@@ -725,5 +738,7 @@
     // Add attributes to metadata
 
-    psMetadataAdd(md, PS_LIST_TAIL, "htAtts", PS_META_HASH, NULL, htAtts);
+    psMetadataAdd(md, PS_LIST_TAIL, "htAtts",
+                  PS_META_HASH | PS_META_DUPLICATE_OK,
+                  NULL, htAtts);
 
     psFree(psTagName);
@@ -828,13 +843,19 @@
     switch(mdType) {
     case PS_META_LIST:
-        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, NULL);
+        psMetadataAdd(md, PS_LIST_TAIL, strName,
+                      mdType | PS_META_DUPLICATE_OK,
+                      NULL, NULL);
         break;
     case PS_META_STR:
-        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, strValue);
+        psMetadataAdd(md, PS_LIST_TAIL, strName,
+                      mdType | PS_META_DUPLICATE_OK,
+                      NULL, strValue);
         break;
     case PS_META_BOOL:
         tempBool = parseBool((char*)strValue, &status);
         if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempBool);
+            psMetadataAdd(md, PS_LIST_TAIL, strName,
+                          mdType | PS_META_DUPLICATE_OK,
+                          NULL, tempBool);
         } else {
             status = 0;
@@ -846,5 +867,7 @@
         tempInt = (psS32)parseValue((char*)strValue, &status);
         if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempInt);
+            psMetadataAdd(md, PS_LIST_TAIL, strName,
+                          mdType | PS_META_DUPLICATE_OK,
+                          NULL, tempInt);
         } else {
             status = 0;
@@ -857,5 +880,7 @@
         tempDbl = parseValue((char*)strValue, &status);
         if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempDbl);
+            psMetadataAdd(md, PS_LIST_TAIL, strName,
+                          mdType | PS_META_DUPLICATE_OK,
+                          NULL, tempDbl);
         } else {
             status = 0;
@@ -966,5 +991,7 @@
     vec = parseVector((char*)strValue, pType, &status);
     if(!status) {
-        psMetadataAdd(md, PS_LIST_TAIL, strName+1, PS_META_VEC, NULL, vec);
+        psMetadataAdd(md, PS_LIST_TAIL, strName+1,
+                      PS_META_VEC | PS_META_DUPLICATE_OK,
+                      NULL, vec);
     } else {
         psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
Index: /trunk/psLib/src/xml/psXML.h
===================================================================
--- /trunk/psLib/src/xml/psXML.h	(revision 3380)
+++ /trunk/psLib/src/xml/psXML.h	(revision 3381)
@@ -1,20 +1,20 @@
 /** @file  psMetadataIO.h
-*
-*  @brief Contains metadata input/output functions.
-*
-*  This file defines functions to read and write metadata to/from an external file.
-*
-*  @ingroup Metadata
-*
-*  @author Ross Harman, MHPCC
-*
-*  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-02-17 19:26:23 $
-*
-*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
-*/
+ *
+ *  @brief Contains metadata input/output functions.
+ *
+ *  This file defines functions to read and write metadata to/from an external file.
+ *
+ *  @ingroup Metadata
+ *
+ *  @author Ross Harman, MHPCC
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-03-07 20:58:50 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
 #ifndef PS_METADATAIO_H
 #define PS_METADATAIO_H
-
 
 /// @addtogroup Metadata
Index: /trunk/psLib/test/astronomy/Makefile.am
===================================================================
--- /trunk/psLib/test/astronomy/Makefile.am	(revision 3380)
+++ /trunk/psLib/test/astronomy/Makefile.am	(revision 3381)
@@ -74,4 +74,6 @@
 	verified 
 
+CLEANFILES = $(TESTS) $(check_DATA)
+
 psTime.config: $(top_srcdir)/etc/pslib/psTime.config.template
 	sed 's|PREFIX|$(top_srcdir)|' $? > $@
Index: /trunk/psLib/test/astronomy/data/test.config
===================================================================
--- /trunk/psLib/test/astronomy/data/test.config	(revision 3380)
+++ /trunk/psLib/test/astronomy/data/test.config	(revision 3381)
@@ -7,6 +7,6 @@
 #  author  Ross Harman, MHPCC
 #
-#  version $Revision: 1.1 $  $Name: not supported by cvs2svn $
-#  date  $Date: 2005-02-17 01:58:43 $
+#  version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+#  date  $Date: 2005-03-07 20:58:50 $
 #
 #  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -74,13 +74,12 @@
 ########## Test 10  ##########
 # The lines below should create a folder node with children that are strings. They should be read by the parser.
-comment *
-comment STR This
-comment STR     is
-comment STR         an
-comment STR             ugly
-comment STR                 comment
-comment STR                         but
-comment STR                             still
-comment STR                                 valid
+comment *STR This
+comment *STR     is
+comment *STR         an
+comment *STR             ugly
+comment *STR                 comment
+comment *STR                         but
+comment *STR                             still
+comment *STR                                 valid
 #
 #
Index: /trunk/psLib/test/astronomy/tst_psMetadataIO.c
===================================================================
--- /trunk/psLib/test/astronomy/tst_psMetadataIO.c	(revision 3380)
+++ /trunk/psLib/test/astronomy/tst_psMetadataIO.c	(revision 3381)
@@ -1,22 +1,23 @@
 /** @file  tst_psMetadataIO.c
-*
-*  @brief Test driver for psMetadataIO functions
-*
-*  This test driver contains the following tests for psMetadata:
-*    Test A - Read config file with overwrite set true
-*    Test B - Read config file with overwrite set false
-*    Test C - Read config file without auto-allocation of metadata
-*    Test D - Attempt to use null fileName argument
-*    Test E - Attempt to open nonexistant file
-*    Test F - Free psMetadata
-*
-*  @author  Ross Harman, MHPCC
-*
-*  @version $Revision: 1.10 $  $Name: not supported by cvs2svn $
-*  @date  $Date: 2005-02-28 23:34:10 $
-*
-*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
-*
-*/
+ *
+ *  @brief Test driver for psMetadataIO functions
+ *
+ *  This test driver contains the following tests for psMetadata:
+ *    Test A - Read config file with overwrite set true
+ *    Test B - Read config file with overwrite set false
+ *    Test C - Read config file without auto-allocation of metadata
+ *    Test D - Attempt to use null fileName argument
+ *    Test E - Attempt to open nonexistant file
+ *    Test F - Free psMetadata
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.11 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-03-07 20:58:50 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
 
 #include <string.h>
@@ -69,5 +70,5 @@
 
     switch (metadataItem->type) {
-    case PS_META_LIST:
+    case PS_META_MULTI:
         printf("Key Value: %17c", ' ');
         break;
@@ -92,5 +93,5 @@
     printf("Key Comment: %s\n", metadataItem->comment);
 
-    if(metadataItem->data.V && metadataItem->type==PS_META_LIST) {
+    if(metadataItem->data.V && metadataItem->type==PS_META_MULTI) {
         printMetadataList(metadataItem->data.V, "    ");
     }
Index: /trunk/psLib/test/astronomy/tst_psMetadata_01.c
===================================================================
--- /trunk/psLib/test/astronomy/tst_psMetadata_01.c	(revision 3380)
+++ /trunk/psLib/test/astronomy/tst_psMetadata_01.c	(revision 3381)
@@ -18,6 +18,6 @@
 *  @author  Ross Harman, MHPCC
 *
-*  @version $Revision: 1.21 $  $Name: not supported by cvs2svn $
-*  @date  $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.22 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -75,5 +75,5 @@
 
     switch (metadataItem->type) {
-    case PS_META_LIST:
+    case PS_META_MULTI:
         printf("Key Value: %17c", ' ');
         break;
@@ -98,5 +98,5 @@
     printf("Key Comment: %s\n", metadataItem->comment);
 
-    if(metadataItem->data.V && metadataItem->type==PS_META_LIST) {
+    if(metadataItem->data.V && metadataItem->type==PS_META_MULTI) {
         printMetadataList(metadataItem->data.V, "    ");
     }
Index: /trunk/psLib/test/astronomy/tst_psMetadata_02.c
===================================================================
--- /trunk/psLib/test/astronomy/tst_psMetadata_02.c	(revision 3380)
+++ /trunk/psLib/test/astronomy/tst_psMetadata_02.c	(revision 3381)
@@ -1,23 +1,24 @@
 /** @file  tst_psMetadata_02.c
-*
-*  @brief Test driver for psMetadata functions
-*
-*  This test driver contains the following tests for psMetadata:
-*     Test A - Allocate metadata items
-*     Test B - Attempt to create metadata item with null name
-*     Test C - Attempt to create metadata item with invalid type
-*     Test D - Allocate metadata
-*     Test E - Attempt to add metadata item to null metadata
-*     Test F - Attempt to add null metadata item to metadata
-*     Test G - Free psMetadata
-*
-*  @author  Ross Harman, MHPCC
-*
-*  @version $Revision: 1.12 $  $Name: not supported by cvs2svn $
-*  @date  $Date: 2005-02-28 23:34:10 $
-*
-*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
-*
-*/
+ *
+ *  @brief Test driver for psMetadata functions
+ *
+ *  This test driver contains the following tests for psMetadata:
+ *     Test A - Allocate metadata items
+ *     Test B - Attempt to create metadata item with null name
+ *     Test C - Attempt to create metadata item with invalid type
+ *     Test D - Allocate metadata
+ *     Test E - Attempt to add metadata item to null metadata
+ *     Test F - Attempt to add null metadata item to metadata
+ *     Test G - Free psMetadata
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.13 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-03-07 20:58:50 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
 
 #include <string.h>
@@ -31,5 +32,5 @@
 
     switch (metadataItem->type) {
-    case PS_META_LIST:
+    case PS_META_MULTI:
         printf("Key Value: %17c", ' ');
         break;
@@ -110,5 +111,5 @@
     printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to add metadata item to null metadata",
                             "Null metadata collection not allowed", 0);
-    psMetadataAddItem(NULL, item1, PS_LIST_HEAD);
+    psMetadataAddItem(NULL, item1, PS_LIST_HEAD, PS_META_DEFAULT);
     printFooter(stdout, "psMetadata", "Test E - Attempt to add metadata item to null metadata", true);
 
@@ -117,5 +118,5 @@
     printNegativeTestHeader(stdout,"psMetadata", "Test F - Attempt to add null metadata item to metadata",
                             "Null metadata item not allowed", 0);
-    psMetadataAddItem(metadata, NULL, PS_LIST_HEAD);
+    psMetadataAddItem(metadata, NULL, PS_LIST_HEAD, PS_META_DEFAULT);
     printFooter(stdout, "psMetadata", "Test F - Attempt to add null metadata item to metadata", true);
 
Index: /trunk/psLib/test/astronomy/tst_psMetadata_03.c
===================================================================
--- /trunk/psLib/test/astronomy/tst_psMetadata_03.c	(revision 3380)
+++ /trunk/psLib/test/astronomy/tst_psMetadata_03.c	(revision 3381)
@@ -18,6 +18,6 @@
 *  @author  Ross Harman, MHPCC
 *
-*  @version $Revision: 1.14 $  $Name: not supported by cvs2svn $
-*  @date  $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.15 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -35,5 +35,5 @@
 
     switch (metadataItem->type) {
-    case PS_META_LIST:
+    case PS_META_MULTI:
         printf("Key Value: %17c", ' ');
         break;
@@ -90,5 +90,5 @@
     // Test B - Remove items from metadata by name
     printPositiveTestHeader(stdout, "psMetadata", "Test B - Remove items from metadata by name");
-    if(!psMetadataAddItem(metadata, item1, PS_LIST_HEAD)) {
+    if(!psMetadataAddItem(metadata, item1, PS_LIST_HEAD, PS_META_DEFAULT)) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return true when adding by name.");
         return 10;
@@ -111,5 +111,5 @@
     // Test C - Remove items from metadata by index
     printPositiveTestHeader(stdout, "psMetadata", "Test C - Remove items from metadata by index");
-    if ( ! psMetadataAddItem(metadata, item3, PS_LIST_HEAD) ) {
+    if ( ! psMetadataAddItem(metadata, item3, PS_LIST_HEAD, PS_META_DEFAULT) ) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return true when adding by index.");
         return 14;
@@ -166,5 +166,5 @@
     mdTable = errMetadata->table;
     errMetadata->table = NULL;
-    if ( psMetadataAddItem(errMetadata, item3, PS_LIST_HEAD) ) {
+    if ( psMetadataAddItem(errMetadata, item3, PS_LIST_HEAD, PS_META_DEFAULT) ) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return false w/ invalid metadata struct w/o hash table.");
         return 21;
@@ -182,5 +182,5 @@
     mdList = errMetadata->list;
     errMetadata->list = NULL;
-    if ( psMetadataAddItem(errMetadata, item3, PS_LIST_HEAD) ) {
+    if ( psMetadataAddItem(errMetadata, item3, PS_LIST_HEAD, PS_META_DEFAULT) ) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return false w/ invalid metadata struct w/o link list.");
         return 22;
@@ -198,5 +198,5 @@
     errName = errItem->name;
     errItem->name = NULL;
-    if ( psMetadataAddItem(errMetadata, errItem, PS_LIST_HEAD) ) {
+    if ( psMetadataAddItem(errMetadata, errItem, PS_LIST_HEAD, PS_META_DEFAULT) ) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return false with item with null name.");
         return 23;
Index: /trunk/psLib/test/astronomy/tst_psMetadata_04.c
===================================================================
--- /trunk/psLib/test/astronomy/tst_psMetadata_04.c	(revision 3380)
+++ /trunk/psLib/test/astronomy/tst_psMetadata_04.c	(revision 3381)
@@ -23,6 +23,6 @@
 *  @author  Ross Harman, MHPCC
 *
-*  @version $Revision: 1.15 $  $Name: not supported by cvs2svn $
-*  @date  $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.16 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -40,5 +40,5 @@
 
     switch (metadataItem->type) {
-    case PS_META_LIST:
+    case PS_META_MULTI:
         printf("Key Value: %17c", ' ');
         break;
@@ -95,10 +95,10 @@
     printMetadataItem(item4);
     printMetadataItem(item5);
-    psMetadataAddItem(metadata, item1, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item2, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item3, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item4, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item5, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item6, PS_LIST_HEAD);
+    psMetadataAddItem(metadata, item1, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item2, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item3, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item4, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item5, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item6, PS_LIST_HEAD, PS_META_DEFAULT);
     psFree(vec);
     printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
Index: /trunk/psLib/test/astronomy/tst_psMetadata_05.c
===================================================================
--- /trunk/psLib/test/astronomy/tst_psMetadata_05.c	(revision 3380)
+++ /trunk/psLib/test/astronomy/tst_psMetadata_05.c	(revision 3381)
@@ -22,6 +22,6 @@
 *  @author  Ross Harman, MHPCC
 *
-*  @version $Revision: 1.20 $  $Name: not supported by cvs2svn $
-*  @date  $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.21 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -39,5 +39,5 @@
 
     switch (metadataItem->type) {
-    case PS_META_LIST:
+    case PS_META_MULTI:
         printf("Key Value: %17c", ' ');
         break;
@@ -92,8 +92,8 @@
     printMetadataItem(item3);
     printMetadataItem(item4);
-    psMetadataAddItem(metadata, item1, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item2, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item3, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item4, PS_LIST_HEAD);
+    psMetadataAddItem(metadata, item1, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item2, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item3, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item4, PS_LIST_HEAD, PS_META_DEFAULT);
     printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
 
Index: /trunk/psLib/test/astronomy/tst_psMetadata_06.c
===================================================================
--- /trunk/psLib/test/astronomy/tst_psMetadata_06.c	(revision 3380)
+++ /trunk/psLib/test/astronomy/tst_psMetadata_06.c	(revision 3381)
@@ -13,6 +13,6 @@
 *  @author  Ross Harman, MHPCC
 *
-*  @version $Revision: 1.10 $  $Name: not supported by cvs2svn $
-*  @date  $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.11 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -30,6 +30,9 @@
 
     switch (metadataItem->type) {
+    case PS_META_MULTI:
+        printf("Key Value: %17c", ' ');
+        break;
     case PS_META_LIST:
-        printf("Key Value: %17c", ' ');
+        printf("Key Value: %15s  ", "psList");
         break;
     case PS_META_BOOL:
@@ -71,5 +74,5 @@
     item1c = psMetadataItemAlloc("myItem1", PS_META_S32, "I am a signed integer", 222);
     item2a = psMetadataItemAlloc("myItem2", PS_META_S32, "I am a signed integer", 333);
-    item2b = psMetadataItemAlloc("myItem2", PS_META_LIST, "I am a folder node", NULL);
+    item2b = psMetadataItemAlloc("myItem2", PS_META_LIST, "I am a list", NULL);
     metadata = psMetadataAlloc();
     printMetadataItem(item1a);
@@ -82,37 +85,60 @@
 
     // Test B - Add leaf node on top of existing leaf node
-    printPositiveTestHeader(stdout, "psMetadata", "Test B - Add leaf node on top of existing leaf node");
-    if(!psMetadataAddItem(metadata, item1a, PS_LIST_HEAD)) {
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - replace an item in the metadata");
+    if(!psMetadataAddItem(metadata, item1a, PS_LIST_HEAD, PS_META_DEFAULT)) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem returned false for adding a node top.");
         return 20;
     }
-    if (!psMetadataAddItem(metadata, item1b, PS_LIST_HEAD)) {
+    psMetadataItem* tempItem = psMetadataLookup(metadata, item1a->name);
+    if (tempItem != item1a) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem didn't add the metadata entry.");
+        return 20;
+    }
+
+    if (!psMetadataAddItem(metadata, item1b, PS_LIST_HEAD, PS_META_REPLACE)) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem returned false for adding a node top.");
         return 21;
     }
 
-    printFooter(stdout, "psMetadata", "Test B - Add leaf node on top of existing leaf node", true);
+    tempItem = psMetadataLookup(metadata, item1a->name);
+    if (tempItem != item1b) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem didn't replace the metadata entry.");
+        return 21;
+    }
+
+    printFooter(stdout, "psMetadata", "Test B - replace an item in the metadata", true);
 
 
     // Test C - Add leaf node to existing folder node
-    printPositiveTestHeader(stdout, "psMetadata", "Test C - Add leaf node to existing folder node");
-    if (!psMetadataAddItem(metadata, item1c, PS_LIST_HEAD)) {
+    printPositiveTestHeader(stdout, "psMetadata", "Test C - add duplicate-key metadata item");
+    if (!psMetadataAddItem(metadata, item1c, PS_LIST_HEAD, PS_META_DUPLICATE_OK)) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem return false for adding a not to existing node.");
         return 22;
     }
-    printFooter(stdout, "psMetadata", "Test C - Add leaf node to existing folder node", true);
+
+    tempItem = psMetadataLookup(metadata, item1a->name);
+    if (tempItem == NULL || tempItem->type != PS_META_MULTI) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem didn't add additional metadata entry of same key.");
+        return 22;
+    }
+    printFooter(stdout, "psMetadata", "Test C - add duplicate-key metadata item", true);
 
 
     // Test D - Add folder node on top of existing leaf node
     printPositiveTestHeader(stdout, "psMetadata", "Test D - Add folder node on top of existing leaf node");
-    if (!psMetadataAddItem(metadata, item2a, PS_LIST_HEAD)) {
+    if (!psMetadataAddItem(metadata, item2a, PS_LIST_HEAD, PS_META_DEFAULT)) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem returned false for adding a node to existing leaf node.");
         return 23;
     }
-    if (!psMetadataAddItem(metadata, item2b, PS_LIST_HEAD)) {
+    if (!psMetadataAddItem(metadata, item2b, PS_LIST_HEAD, PS_META_DUPLICATE_OK)) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem returned false for adding a nod to existing leaf node.");
         return 24;
     }
     printFooter(stdout, "psMetadata", "Test D - Add folder node on top of existing leaf node", true);
+    tempItem = psMetadataLookup(metadata, item1a->name);
+    if (tempItem == NULL || tempItem->type != PS_META_MULTI) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem didn't add additional metadata entry of same key.");
+        return 24;
+    }
 
 
Index: /trunk/psLib/test/astronomy/verified/tst_psMetadataIO.stderr
===================================================================
--- /trunk/psLib/test/astronomy/verified/tst_psMetadataIO.stderr	(revision 3380)
+++ /trunk/psLib/test/astronomy/verified/tst_psMetadataIO.stderr	(revision 3381)
@@ -1,40 +1,44 @@
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    Failed to parse the value '9876.54qqq32' of metadata item xPosition, type F64, on line 90 of test.config.
+    Failed to parse the value '9876.54qqq32' of metadata item xPosition, type F64, on line 89 of test.config.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    Failed to read a metadata value on line 96 of test.config.
+    Failed to read a metadata value on line 95 of test.config.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    Metadata type '99.999', found on line 102 of test.config, is not invalid.
+    Metadata type '99.999', found on line 101 of test.config, is not invalid.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    More than one '*' character not allowed.  Found on line 108 of test.config.
+    More than one '*' character not allowed.  Found on line 107 of test.config.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    More than one '@' character not allowed.  Found on line 114 of test.config.
+    More than one '@' character not allowed.  Found on line 113 of test.config.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    More than one '~' character not allowed.  Found on line 120 of test.config.
+    More than one '~' character not allowed.  Found on line 119 of test.config.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    Failed to parse the value '9876.54qqq32' of metadata item xPosition, type F64, on line 90 of test.config.
+    Failed to parse the value '9876.54qqq32' of metadata item xPosition, type F64, on line 89 of test.config.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    Failed to read a metadata value on line 96 of test.config.
+    Failed to read a metadata value on line 95 of test.config.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    Metadata type '99.999', found on line 102 of test.config, is not invalid.
+    Metadata type '99.999', found on line 101 of test.config, is not invalid.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    More than one '*' character not allowed.  Found on line 108 of test.config.
+    More than one '*' character not allowed.  Found on line 107 of test.config.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    More than one '@' character not allowed.  Found on line 114 of test.config.
+    More than one '@' character not allowed.  Found on line 113 of test.config.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    More than one '~' character not allowed.  Found on line 120 of test.config.
+    More than one '~' character not allowed.  Found on line 119 of test.config.
+<DATE><TIME>|<HOST>|E|psMetadataAddItem (FILE:LINENO)
+    Duplicate metadata item name is not allowed.  Use a psMetadataFlags option to allow such action.
+<DATE><TIME>|<HOST>|E|psMetadataAddV (FILE:LINENO)
+    Failed to add metadata item to metadata collection list.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    Duplicate Metadata item, speed, found on line 128 of test.config.  Overwrite not allowed.
+    Duplicate Metadata item, speed, found on line 127 of test.config.  Overwrite not allowed.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    Failed to parse the value '9876.54qqq32' of metadata item xPosition, type F64, on line 90 of test.config.
+    Failed to parse the value '9876.54qqq32' of metadata item xPosition, type F64, on line 89 of test.config.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    Failed to read a metadata value on line 96 of test.config.
+    Failed to read a metadata value on line 95 of test.config.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    Metadata type '99.999', found on line 102 of test.config, is not invalid.
+    Metadata type '99.999', found on line 101 of test.config, is not invalid.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    More than one '*' character not allowed.  Found on line 108 of test.config.
+    More than one '*' character not allowed.  Found on line 107 of test.config.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    More than one '@' character not allowed.  Found on line 114 of test.config.
+    More than one '@' character not allowed.  Found on line 113 of test.config.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
-    More than one '~' character not allowed.  Found on line 120 of test.config.
+    More than one '~' character not allowed.  Found on line 119 of test.config.
 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
     Unallowable operation: fileName is NULL.
Index: /trunk/psLib/test/astronomy/verified/tst_psMetadataIO.stdout
===================================================================
--- /trunk/psLib/test/astronomy/verified/tst_psMetadataIO.stdout	(revision 3380)
+++ /trunk/psLib/test/astronomy/verified/tst_psMetadataIO.stdout	(revision 3381)
@@ -26,5 +26,5 @@
 
 Contents of metadata table:
- Key Name:  comment  Key mdType: 4  Key Value:                  Key Comment: 
+ Key Name:  comment  Key mdType: 14  Key Value:                  Key Comment: 
     Key Name:  comment  Key mdType: 5  Key Value:            This  Key Comment: 
     Key Name:  comment  Key mdType: 5  Key Value:              is  Key Comment: 
@@ -73,5 +73,5 @@
 
 Contents of metadata table:
- Key Name:  comment  Key mdType: 4  Key Value:                  Key Comment: 
+ Key Name:  comment  Key mdType: 14  Key Value:                  Key Comment: 
     Key Name:  comment  Key mdType: 5  Key Value:            This  Key Comment: 
     Key Name:  comment  Key mdType: 5  Key Value:              is  Key Comment: 
@@ -120,5 +120,5 @@
 
 Contents of metadata table:
- Key Name:  comment  Key mdType: 4  Key Value:                  Key Comment: 
+ Key Name:  comment  Key mdType: 14  Key Value:                  Key Comment: 
     Key Name:  comment  Key mdType: 5  Key Value:            This  Key Comment: 
     Key Name:  comment  Key mdType: 5  Key Value:              is  Key Comment: 
Index: /trunk/psLib/test/astronomy/verified/tst_psMetadata_01.stderr
===================================================================
--- /trunk/psLib/test/astronomy/verified/tst_psMetadata_01.stderr	(revision 3380)
+++ /trunk/psLib/test/astronomy/verified/tst_psMetadata_01.stderr	(revision 3381)
@@ -1,6 +1,2 @@
-<DATE><TIME>|<HOST>|E|psListRemoveData (FILE:LINENO)
-    Specified data item is not found in the psList.
-<DATE><TIME>|<HOST>|E|psMetadataRemove (FILE:LINENO)
-    Failed to remove metadata item, HISTORY, from metadata list.
 <DATE><TIME>|<HOST>|E|psMetadataReadHeader (FILE:LINENO)
     Unallowable operation: fileName is NULL.
Index: /trunk/psLib/test/astronomy/verified/tst_psMetadata_01.stdout
===================================================================
--- /trunk/psLib/test/astronomy/verified/tst_psMetadata_01.stdout	(revision 3380)
+++ /trunk/psLib/test/astronomy/verified/tst_psMetadata_01.stdout	(revision 3381)
@@ -44,9 +44,9 @@
  Key Name:   PCOUNT  Key mdType: 0  Key Value:               0  Key Comment: required keyword; must = 0
  Key Name: XTENSION  Key mdType: 5  Key Value:      'IMAGE   '  Key Comment: IMAGE extension
- Key Name:   BITPIX  Key mdType: 4  Key Value:                  Key Comment: 
+ Key Name:   BITPIX  Key mdType: 14  Key Value:                  Key Comment: 
     Key Name:   BITPIX  Key mdType: 0  Key Value:             -64  Key Comment: number of bits per data pixel
     Key Name:   BITPIX  Key mdType: 0  Key Value:             -64  Key Comment: number of bits per data pixel
  Key Name:   GCOUNT  Key mdType: 0  Key Value:               1  Key Comment: required keyword; must = 1
- Key Name:  HISTORY  Key mdType: 4  Key Value:                  Key Comment: 
+ Key Name:  HISTORY  Key mdType: 14  Key Value:                  Key Comment: 
     Key Name:  HISTORY  Key mdType: 5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
     Key Name:  HISTORY  Key mdType: 5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
@@ -81,5 +81,5 @@
  Key Name:   GCOUNT  Key mdType: 0  Key Value:               1  Key Comment: required keyword; must = 1
  Key Name:   BITPIX  Key mdType: 0  Key Value:             -64  Key Comment: number of bits per data pixel
- Key Name:  HISTORY  Key mdType: 4  Key Value:                  Key Comment: 
+ Key Name:  HISTORY  Key mdType: 14  Key Value:                  Key Comment: 
     Key Name:  HISTORY  Key mdType: 5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
     Key Name:  HISTORY  Key mdType: 5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
@@ -104,6 +104,4 @@
  Key Name:   GCOUNT  Key mdType: 0  Key Value:               1  Key Comment: required keyword; must = 1
  Key Name:  EXTNAME  Key mdType: 5  Key Value:     'MY_DATA_2'  Key Comment: 
- Key Name:  HISTORY  Key mdType: 5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
- Key Name:  HISTORY  Key mdType: 5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
 
 Contents of metadata table:
@@ -114,7 +112,4 @@
  Key Name:   GCOUNT  Key mdType: 0  Key Value:               1  Key Comment: required keyword; must = 1
  Key Name:   BITPIX  Key mdType: 0  Key Value:             -64  Key Comment: number of bits per data pixel
- Key Name:  HISTORY  Key mdType: 4  Key Value:                  Key Comment: 
-    Key Name:  HISTORY  Key mdType: 5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
-    Key Name:  HISTORY  Key mdType: 5  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
  Key Name:  EXTNAME  Key mdType: 5  Key Value:     'MY_DATA_2'  Key Comment: 
 
Index: /trunk/psLib/test/astronomy/verified/tst_psMetadata_02.stderr
===================================================================
--- /trunk/psLib/test/astronomy/verified/tst_psMetadata_02.stderr	(revision 3380)
+++ /trunk/psLib/test/astronomy/verified/tst_psMetadata_02.stderr	(revision 3381)
@@ -4,5 +4,5 @@
     Unallowable operation: name is NULL.
 <DATE><TIME>|<HOST>|E|psMetadataItemAllocV (FILE:LINENO)
-    Specified psMetadataType, 14, is not supported.
+    Specified psMetadataType, 15, is not supported.
 <DATE><TIME>|<HOST>|E|psMetadataAddItem (FILE:LINENO)
     Unallowable operation: md is NULL.
Index: /trunk/psLib/test/astronomy/verified/tst_psMetadata_03.stderr
===================================================================
--- /trunk/psLib/test/astronomy/verified/tst_psMetadata_03.stderr	(revision 3380)
+++ /trunk/psLib/test/astronomy/verified/tst_psMetadata_03.stderr	(revision 3381)
@@ -2,5 +2,5 @@
     Unallowable operation: md is NULL.
 <DATE><TIME>|<HOST>|E|psMetadataRemove (FILE:LINENO)
-    Could not find metadata item, AARGH.
+    Failed to remove metadata item, AARGH, from metadata table.
 <DATE><TIME>|<HOST>|E|psMetadataRemove (FILE:LINENO)
     Could not find metadata item at index 22.
@@ -17,4 +17,4 @@
 <DATE><TIME>|<HOST>|E|psMetadataAddItem (FILE:LINENO)
     Unallowable operation: md->table is NULL.
-<DATE><TIME>|<HOST>|E|psMetadataAdd (FILE:LINENO)
+<DATE><TIME>|<HOST>|E|psMetadataAddV (FILE:LINENO)
     Failed to add metadata item to metadata collection list.
Index: /trunk/psLib/test/astronomy/verified/tst_psMetadata_06.stdout
===================================================================
--- /trunk/psLib/test/astronomy/verified/tst_psMetadata_06.stdout	(revision 3380)
+++ /trunk/psLib/test/astronomy/verified/tst_psMetadata_06.stdout	(revision 3381)
@@ -9,5 +9,5 @@
 Key Name:  myItem1  Key mdType:  0  Key Value:             222  Key Comment: I am a signed integer
 Key Name:  myItem2  Key mdType:  0  Key Value:             333  Key Comment: I am a signed integer
-Key Name:  myItem2  Key mdType:  4  Key Value:                  Key Comment: I am a folder node
+Key Name:  myItem2  Key mdType:  4  Key Value:          psList  Key Comment: I am a list
 
 ---> TESTPOINT PASSED (psMetadata{Test A - Allocate metadata and items} | tst_psMetadata_06.c)
@@ -15,19 +15,19 @@
 /***************************** TESTPOINT ******************************************\
 *             TestFile: tst_psMetadata_06.c                                        *
-*            TestPoint: psMetadata{Test B - Add leaf node on top of existing leaf node} *
+*            TestPoint: psMetadata{Test B - replace an item in the metadata}       *
 *             TestType: Positive                                                   *
 \**********************************************************************************/
 
 
----> TESTPOINT PASSED (psMetadata{Test B - Add leaf node on top of existing leaf node} | tst_psMetadata_06.c)
+---> TESTPOINT PASSED (psMetadata{Test B - replace an item in the metadata} | tst_psMetadata_06.c)
 
 /***************************** TESTPOINT ******************************************\
 *             TestFile: tst_psMetadata_06.c                                        *
-*            TestPoint: psMetadata{Test C - Add leaf node to existing folder node} *
+*            TestPoint: psMetadata{Test C - add duplicate-key metadata item}       *
 *             TestType: Positive                                                   *
 \**********************************************************************************/
 
 
----> TESTPOINT PASSED (psMetadata{Test C - Add leaf node to existing folder node} | tst_psMetadata_06.c)
+---> TESTPOINT PASSED (psMetadata{Test C - add duplicate-key metadata item} | tst_psMetadata_06.c)
 
 /***************************** TESTPOINT ******************************************\
Index: /trunk/psLib/test/collections/Makefile.am
===================================================================
--- /trunk/psLib/test/collections/Makefile.am	(revision 3380)
+++ /trunk/psLib/test/collections/Makefile.am	(revision 3381)
@@ -36,4 +36,6 @@
 TESTS_ENVIRONMENT = perl $(top_srcdir)/test/runTest -verified=$(srcdir)/verified 
 
+CLEANFILES = $(TESTS) $(check_DATA)
+
 tests: $(TESTS)
 
Index: /trunk/psLib/test/collections/tst_psMetadataIO.c
===================================================================
--- /trunk/psLib/test/collections/tst_psMetadataIO.c	(revision 3380)
+++ /trunk/psLib/test/collections/tst_psMetadataIO.c	(revision 3381)
@@ -1,22 +1,23 @@
 /** @file  tst_psMetadataIO.c
-*
-*  @brief Test driver for psMetadataIO functions
-*
-*  This test driver contains the following tests for psMetadata:
-*    Test A - Read config file with overwrite set true
-*    Test B - Read config file with overwrite set false
-*    Test C - Read config file without auto-allocation of metadata
-*    Test D - Attempt to use null fileName argument
-*    Test E - Attempt to open nonexistant file
-*    Test F - Free psMetadata
-*
-*  @author  Ross Harman, MHPCC
-*
-*  @version $Revision: 1.10 $  $Name: not supported by cvs2svn $
-*  @date  $Date: 2005-02-28 23:34:10 $
-*
-*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
-*
-*/
+ *
+ *  @brief Test driver for psMetadataIO functions
+ *
+ *  This test driver contains the following tests for psMetadata:
+ *    Test A - Read config file with overwrite set true
+ *    Test B - Read config file with overwrite set false
+ *    Test C - Read config file without auto-allocation of metadata
+ *    Test D - Attempt to use null fileName argument
+ *    Test E - Attempt to open nonexistant file
+ *    Test F - Free psMetadata
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.11 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-03-07 20:58:50 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
 
 #include <string.h>
@@ -69,5 +70,5 @@
 
     switch (metadataItem->type) {
-    case PS_META_LIST:
+    case PS_META_MULTI:
         printf("Key Value: %17c", ' ');
         break;
@@ -92,5 +93,5 @@
     printf("Key Comment: %s\n", metadataItem->comment);
 
-    if(metadataItem->data.V && metadataItem->type==PS_META_LIST) {
+    if(metadataItem->data.V && metadataItem->type==PS_META_MULTI) {
         printMetadataList(metadataItem->data.V, "    ");
     }
Index: /trunk/psLib/test/collections/tst_psMetadata_01.c
===================================================================
--- /trunk/psLib/test/collections/tst_psMetadata_01.c	(revision 3380)
+++ /trunk/psLib/test/collections/tst_psMetadata_01.c	(revision 3381)
@@ -18,6 +18,6 @@
 *  @author  Ross Harman, MHPCC
 *
-*  @version $Revision: 1.21 $  $Name: not supported by cvs2svn $
-*  @date  $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.22 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -75,5 +75,5 @@
 
     switch (metadataItem->type) {
-    case PS_META_LIST:
+    case PS_META_MULTI:
         printf("Key Value: %17c", ' ');
         break;
@@ -98,5 +98,5 @@
     printf("Key Comment: %s\n", metadataItem->comment);
 
-    if(metadataItem->data.V && metadataItem->type==PS_META_LIST) {
+    if(metadataItem->data.V && metadataItem->type==PS_META_MULTI) {
         printMetadataList(metadataItem->data.V, "    ");
     }
Index: /trunk/psLib/test/collections/tst_psMetadata_02.c
===================================================================
--- /trunk/psLib/test/collections/tst_psMetadata_02.c	(revision 3380)
+++ /trunk/psLib/test/collections/tst_psMetadata_02.c	(revision 3381)
@@ -1,23 +1,24 @@
 /** @file  tst_psMetadata_02.c
-*
-*  @brief Test driver for psMetadata functions
-*
-*  This test driver contains the following tests for psMetadata:
-*     Test A - Allocate metadata items
-*     Test B - Attempt to create metadata item with null name
-*     Test C - Attempt to create metadata item with invalid type
-*     Test D - Allocate metadata
-*     Test E - Attempt to add metadata item to null metadata
-*     Test F - Attempt to add null metadata item to metadata
-*     Test G - Free psMetadata
-*
-*  @author  Ross Harman, MHPCC
-*
-*  @version $Revision: 1.12 $  $Name: not supported by cvs2svn $
-*  @date  $Date: 2005-02-28 23:34:10 $
-*
-*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
-*
-*/
+ *
+ *  @brief Test driver for psMetadata functions
+ *
+ *  This test driver contains the following tests for psMetadata:
+ *     Test A - Allocate metadata items
+ *     Test B - Attempt to create metadata item with null name
+ *     Test C - Attempt to create metadata item with invalid type
+ *     Test D - Allocate metadata
+ *     Test E - Attempt to add metadata item to null metadata
+ *     Test F - Attempt to add null metadata item to metadata
+ *     Test G - Free psMetadata
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.13 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-03-07 20:58:50 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
 
 #include <string.h>
@@ -31,5 +32,5 @@
 
     switch (metadataItem->type) {
-    case PS_META_LIST:
+    case PS_META_MULTI:
         printf("Key Value: %17c", ' ');
         break;
@@ -110,5 +111,5 @@
     printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to add metadata item to null metadata",
                             "Null metadata collection not allowed", 0);
-    psMetadataAddItem(NULL, item1, PS_LIST_HEAD);
+    psMetadataAddItem(NULL, item1, PS_LIST_HEAD, PS_META_DEFAULT);
     printFooter(stdout, "psMetadata", "Test E - Attempt to add metadata item to null metadata", true);
 
@@ -117,5 +118,5 @@
     printNegativeTestHeader(stdout,"psMetadata", "Test F - Attempt to add null metadata item to metadata",
                             "Null metadata item not allowed", 0);
-    psMetadataAddItem(metadata, NULL, PS_LIST_HEAD);
+    psMetadataAddItem(metadata, NULL, PS_LIST_HEAD, PS_META_DEFAULT);
     printFooter(stdout, "psMetadata", "Test F - Attempt to add null metadata item to metadata", true);
 
Index: /trunk/psLib/test/collections/tst_psMetadata_03.c
===================================================================
--- /trunk/psLib/test/collections/tst_psMetadata_03.c	(revision 3380)
+++ /trunk/psLib/test/collections/tst_psMetadata_03.c	(revision 3381)
@@ -18,6 +18,6 @@
 *  @author  Ross Harman, MHPCC
 *
-*  @version $Revision: 1.14 $  $Name: not supported by cvs2svn $
-*  @date  $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.15 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -35,5 +35,5 @@
 
     switch (metadataItem->type) {
-    case PS_META_LIST:
+    case PS_META_MULTI:
         printf("Key Value: %17c", ' ');
         break;
@@ -90,5 +90,5 @@
     // Test B - Remove items from metadata by name
     printPositiveTestHeader(stdout, "psMetadata", "Test B - Remove items from metadata by name");
-    if(!psMetadataAddItem(metadata, item1, PS_LIST_HEAD)) {
+    if(!psMetadataAddItem(metadata, item1, PS_LIST_HEAD, PS_META_DEFAULT)) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return true when adding by name.");
         return 10;
@@ -111,5 +111,5 @@
     // Test C - Remove items from metadata by index
     printPositiveTestHeader(stdout, "psMetadata", "Test C - Remove items from metadata by index");
-    if ( ! psMetadataAddItem(metadata, item3, PS_LIST_HEAD) ) {
+    if ( ! psMetadataAddItem(metadata, item3, PS_LIST_HEAD, PS_META_DEFAULT) ) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return true when adding by index.");
         return 14;
@@ -166,5 +166,5 @@
     mdTable = errMetadata->table;
     errMetadata->table = NULL;
-    if ( psMetadataAddItem(errMetadata, item3, PS_LIST_HEAD) ) {
+    if ( psMetadataAddItem(errMetadata, item3, PS_LIST_HEAD, PS_META_DEFAULT) ) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return false w/ invalid metadata struct w/o hash table.");
         return 21;
@@ -182,5 +182,5 @@
     mdList = errMetadata->list;
     errMetadata->list = NULL;
-    if ( psMetadataAddItem(errMetadata, item3, PS_LIST_HEAD) ) {
+    if ( psMetadataAddItem(errMetadata, item3, PS_LIST_HEAD, PS_META_DEFAULT) ) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return false w/ invalid metadata struct w/o link list.");
         return 22;
@@ -198,5 +198,5 @@
     errName = errItem->name;
     errItem->name = NULL;
-    if ( psMetadataAddItem(errMetadata, errItem, PS_LIST_HEAD) ) {
+    if ( psMetadataAddItem(errMetadata, errItem, PS_LIST_HEAD, PS_META_DEFAULT) ) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return false with item with null name.");
         return 23;
Index: /trunk/psLib/test/collections/tst_psMetadata_04.c
===================================================================
--- /trunk/psLib/test/collections/tst_psMetadata_04.c	(revision 3380)
+++ /trunk/psLib/test/collections/tst_psMetadata_04.c	(revision 3381)
@@ -23,6 +23,6 @@
 *  @author  Ross Harman, MHPCC
 *
-*  @version $Revision: 1.15 $  $Name: not supported by cvs2svn $
-*  @date  $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.16 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -40,5 +40,5 @@
 
     switch (metadataItem->type) {
-    case PS_META_LIST:
+    case PS_META_MULTI:
         printf("Key Value: %17c", ' ');
         break;
@@ -95,10 +95,10 @@
     printMetadataItem(item4);
     printMetadataItem(item5);
-    psMetadataAddItem(metadata, item1, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item2, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item3, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item4, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item5, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item6, PS_LIST_HEAD);
+    psMetadataAddItem(metadata, item1, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item2, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item3, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item4, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item5, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item6, PS_LIST_HEAD, PS_META_DEFAULT);
     psFree(vec);
     printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
Index: /trunk/psLib/test/collections/tst_psMetadata_05.c
===================================================================
--- /trunk/psLib/test/collections/tst_psMetadata_05.c	(revision 3380)
+++ /trunk/psLib/test/collections/tst_psMetadata_05.c	(revision 3381)
@@ -22,6 +22,6 @@
 *  @author  Ross Harman, MHPCC
 *
-*  @version $Revision: 1.20 $  $Name: not supported by cvs2svn $
-*  @date  $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.21 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -39,5 +39,5 @@
 
     switch (metadataItem->type) {
-    case PS_META_LIST:
+    case PS_META_MULTI:
         printf("Key Value: %17c", ' ');
         break;
@@ -92,8 +92,8 @@
     printMetadataItem(item3);
     printMetadataItem(item4);
-    psMetadataAddItem(metadata, item1, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item2, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item3, PS_LIST_HEAD);
-    psMetadataAddItem(metadata, item4, PS_LIST_HEAD);
+    psMetadataAddItem(metadata, item1, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item2, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item3, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item4, PS_LIST_HEAD, PS_META_DEFAULT);
     printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
 
Index: /trunk/psLib/test/collections/tst_psMetadata_06.c
===================================================================
--- /trunk/psLib/test/collections/tst_psMetadata_06.c	(revision 3380)
+++ /trunk/psLib/test/collections/tst_psMetadata_06.c	(revision 3381)
@@ -13,6 +13,6 @@
 *  @author  Ross Harman, MHPCC
 *
-*  @version $Revision: 1.10 $  $Name: not supported by cvs2svn $
-*  @date  $Date: 2005-02-28 23:34:10 $
+*  @version $Revision: 1.11 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-03-07 20:58:50 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -30,6 +30,9 @@
 
     switch (metadataItem->type) {
+    case PS_META_MULTI:
+        printf("Key Value: %17c", ' ');
+        break;
     case PS_META_LIST:
-        printf("Key Value: %17c", ' ');
+        printf("Key Value: %15s  ", "psList");
         break;
     case PS_META_BOOL:
@@ -71,5 +74,5 @@
     item1c = psMetadataItemAlloc("myItem1", PS_META_S32, "I am a signed integer", 222);
     item2a = psMetadataItemAlloc("myItem2", PS_META_S32, "I am a signed integer", 333);
-    item2b = psMetadataItemAlloc("myItem2", PS_META_LIST, "I am a folder node", NULL);
+    item2b = psMetadataItemAlloc("myItem2", PS_META_LIST, "I am a list", NULL);
     metadata = psMetadataAlloc();
     printMetadataItem(item1a);
@@ -82,37 +85,60 @@
 
     // Test B - Add leaf node on top of existing leaf node
-    printPositiveTestHeader(stdout, "psMetadata", "Test B - Add leaf node on top of existing leaf node");
-    if(!psMetadataAddItem(metadata, item1a, PS_LIST_HEAD)) {
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - replace an item in the metadata");
+    if(!psMetadataAddItem(metadata, item1a, PS_LIST_HEAD, PS_META_DEFAULT)) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem returned false for adding a node top.");
         return 20;
     }
-    if (!psMetadataAddItem(metadata, item1b, PS_LIST_HEAD)) {
+    psMetadataItem* tempItem = psMetadataLookup(metadata, item1a->name);
+    if (tempItem != item1a) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem didn't add the metadata entry.");
+        return 20;
+    }
+
+    if (!psMetadataAddItem(metadata, item1b, PS_LIST_HEAD, PS_META_REPLACE)) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem returned false for adding a node top.");
         return 21;
     }
 
-    printFooter(stdout, "psMetadata", "Test B - Add leaf node on top of existing leaf node", true);
+    tempItem = psMetadataLookup(metadata, item1a->name);
+    if (tempItem != item1b) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem didn't replace the metadata entry.");
+        return 21;
+    }
+
+    printFooter(stdout, "psMetadata", "Test B - replace an item in the metadata", true);
 
 
     // Test C - Add leaf node to existing folder node
-    printPositiveTestHeader(stdout, "psMetadata", "Test C - Add leaf node to existing folder node");
-    if (!psMetadataAddItem(metadata, item1c, PS_LIST_HEAD)) {
+    printPositiveTestHeader(stdout, "psMetadata", "Test C - add duplicate-key metadata item");
+    if (!psMetadataAddItem(metadata, item1c, PS_LIST_HEAD, PS_META_DUPLICATE_OK)) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem return false for adding a not to existing node.");
         return 22;
     }
-    printFooter(stdout, "psMetadata", "Test C - Add leaf node to existing folder node", true);
+
+    tempItem = psMetadataLookup(metadata, item1a->name);
+    if (tempItem == NULL || tempItem->type != PS_META_MULTI) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem didn't add additional metadata entry of same key.");
+        return 22;
+    }
+    printFooter(stdout, "psMetadata", "Test C - add duplicate-key metadata item", true);
 
 
     // Test D - Add folder node on top of existing leaf node
     printPositiveTestHeader(stdout, "psMetadata", "Test D - Add folder node on top of existing leaf node");
-    if (!psMetadataAddItem(metadata, item2a, PS_LIST_HEAD)) {
+    if (!psMetadataAddItem(metadata, item2a, PS_LIST_HEAD, PS_META_DEFAULT)) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem returned false for adding a node to existing leaf node.");
         return 23;
     }
-    if (!psMetadataAddItem(metadata, item2b, PS_LIST_HEAD)) {
+    if (!psMetadataAddItem(metadata, item2b, PS_LIST_HEAD, PS_META_DUPLICATE_OK)) {
         psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem returned false for adding a nod to existing leaf node.");
         return 24;
     }
     printFooter(stdout, "psMetadata", "Test D - Add folder node on top of existing leaf node", true);
+    tempItem = psMetadataLookup(metadata, item1a->name);
+    if (tempItem == NULL || tempItem->type != PS_META_MULTI) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem didn't add additional metadata entry of same key.");
+        return 24;
+    }
 
 
Index: /trunk/psLib/test/dataIO/Makefile.am
===================================================================
--- /trunk/psLib/test/dataIO/Makefile.am	(revision 3380)
+++ /trunk/psLib/test/dataIO/Makefile.am	(revision 3381)
@@ -27,4 +27,6 @@
 tests: $(TESTS)
 
+CLEANFILES = $(TESTS) $(check_DATA)
+
 tst_psLookupTable_01_SOURCES =  tst_psLookupTable_01.c
 tst_psFits_SOURCES =  tst_psFits.c
Index: /trunk/psLib/test/dataManip/Makefile.am
===================================================================
--- /trunk/psLib/test/dataManip/Makefile.am	(revision 3380)
+++ /trunk/psLib/test/dataManip/Makefile.am	(revision 3381)
@@ -60,4 +60,6 @@
 check_PROGRAMS = $(TESTS)
 
+CLEANFILES = $(TESTS) $(check_DATA)
+
 TESTS_ENVIRONMENT = perl $(top_srcdir)/test/runTest -verified=$(srcdir)/verified 
 
Index: /trunk/psLib/test/fileUtils/Makefile.am
===================================================================
--- /trunk/psLib/test/fileUtils/Makefile.am	(revision 3380)
+++ /trunk/psLib/test/fileUtils/Makefile.am	(revision 3381)
@@ -27,4 +27,6 @@
 tests: $(TESTS)
 
+CLEANFILES = $(TESTS) $(check_DATA)
+
 tst_psLookupTable_01_SOURCES =  tst_psLookupTable_01.c
 tst_psFits_SOURCES =  tst_psFits.c
Index: /trunk/psLib/test/image/Makefile.am
===================================================================
--- /trunk/psLib/test/image/Makefile.am	(revision 3380)
+++ /trunk/psLib/test/image/Makefile.am	(revision 3381)
@@ -35,4 +35,6 @@
 TESTS_ENVIRONMENT = perl $(top_srcdir)/test/runTest -verified=$(srcdir)/verified 
 
+CLEANFILES = $(TESTS) $(check_DATA)
+
 tests: $(TESTS)
 
Index: /trunk/psLib/test/sysUtils/Makefile.am
===================================================================
--- /trunk/psLib/test/sysUtils/Makefile.am	(revision 3380)
+++ /trunk/psLib/test/sysUtils/Makefile.am	(revision 3381)
@@ -28,4 +28,6 @@
 TESTS_ENVIRONMENT = perl $(top_srcdir)/test/runTest -verified=$(srcdir)/verified 
 
+CLEANFILES = $(TESTS) $(check_DATA)
+
 tests: $(TESTS)
 
