Index: /trunk/psLib/src/astronomy/psMetadata.c
===================================================================
--- /trunk/psLib/src/astronomy/psMetadata.c	(revision 1350)
+++ /trunk/psLib/src/astronomy/psMetadata.c	(revision 1351)
@@ -1,19 +1,19 @@
 /** @file  psMetadata.c
- *
- *
- *  @brief Contains metadata struuctures, enumerations and functions prototypes
- *
- *  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
- *  prototypes necessary creating psLib metadata APIs
- *
- *  @ingroup Metadata
- *
- *  @author Ross Harman, MHPCC
- *
- *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-07-29 02:04:20 $
- *
- *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
- */
+*
+*
+*  @brief Contains metadata struuctures, enumerations and functions prototypes
+*
+*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+*  prototypes necessary creating psLib metadata APIs
+*
+*  @ingroup Metadata
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-07-30 19:36:52 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
 
 /******************************************************************************/
@@ -24,4 +24,5 @@
 #include<string.h>
 
+#include "fitsio.h"
 #include "psType.h"
 #include "psMemory.h"
@@ -37,5 +38,9 @@
 /******************************************************************************/
 
-// None
+// Maximum metadata length string
+#define MAX_VAL_SIZE 1024
+
+// Maximum metadata error length
+#define MAX_ERR_MESSAGE_LENGTH 1024
 
 /******************************************************************************/
@@ -60,33 +65,33 @@
 /*  FUNCTION IMPLEMENTATION - LOCAL                                          */
 /*****************************************************************************/
-static void metadataItemFree(psMetadataItem *metadataItem)
+static void metadataItemFree( psMetadataItem *metadataItem )
 {
     psMetadataType type;
-
+    
     type = metadataItem->type;
-
-    if (metadataItem == NULL) {
-        return;
-    }
-
-    psFree(metadataItem->name);
-    psFree(metadataItem->comment);
-
-    if(type==PS_META_STR || type==PS_META_IMG || type==PS_META_JPEG || type==PS_META_PNG ||
-            type==PS_META_ASTROM || type==PS_META_UNKNOWN) {
-        psFree(metadataItem->data.V);
-    }
-
-    psFree(metadataItem->items);
-}
-
-static void metadataFree(psMetadata *metadata)
-{
-    if (metadata == NULL) {
-        return;
-    }
-
-    psFree(metadata->list);
-    psFree(metadata->table);
+    
+    if ( metadataItem == NULL ) {
+            return ;
+        }
+        
+    psFree( metadataItem->name );
+    psFree( metadataItem->comment );
+    
+    if ( type == PS_META_STR || type == PS_META_IMG || type == PS_META_JPEG || type == PS_META_PNG ||
+            type == PS_META_ASTROM || type == PS_META_UNKNOWN ) {
+            psFree( metadataItem->data.V );
+        }
+        
+    psFree( metadataItem->items );
+}
+
+static void metadataFree( psMetadata *metadata )
+{
+    if ( metadata == NULL ) {
+            return ;
+        }
+        
+    psFree( metadata->list );
+    psFree( metadata->table );
 }
 
@@ -95,279 +100,582 @@
 /*****************************************************************************/
 
-psMetadataItem *psMetadataItemAlloc(const char *name, psMetadataType type, const char *comment, ...)
+psMetadataItem *psMetadataItemAlloc( const char *name, psMetadataType type, const char *comment, ... )
 {
     va_list argPtr;
     psMetadataItem *metadataItem = NULL;
-
+    
     // Get the variable list parameters to pass to allocation function
-    va_start(argPtr, comment);
-
+    va_start( argPtr, comment );
+    
     // Call metadata item allocation
-    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
-
+    metadataItem = psMetadataItemAllocV( name, type, comment, argPtr );
+    
     // Clean up stack after variable arguement has been used
-    va_end(argPtr);
-
+    va_end( argPtr );
+    
     return metadataItem;
 }
 
-psMetadataItem *psMetadataItemAllocV(const char *name, psMetadataType type, const char *comment, va_list argPtr)
-{
-    psMetadataItem *metadataItem = NULL;
-
-    if(name == NULL) {
-        psError(__func__, "Null value for string not allowed");
-        return NULL;
-    }
-
+psMetadataItem *psMetadataItemAllocV( const char *name, psMetadataType type, const char *comment, va_list argPtr )
+{
+    psMetadataItem * metadataItem = NULL;
+    
+    if ( name == NULL ) {
+            psError( __func__, "Null value for string not allowed" );
+            return NULL;
+        }
+        
     // Allocate metadata item
-    metadataItem = (psMetadataItem *)psAlloc(sizeof(psMetadataItem));
-    if(metadataItem == NULL) {
-        psAbort(__func__,"Failed to allocate memory");
-    }
-
+    metadataItem = ( psMetadataItem * ) psAlloc( sizeof( psMetadataItem ) );
+    if ( metadataItem == NULL ) {
+            psAbort( __func__, "Failed to allocate memory" );
+        }
+        
     // Set deallocator
-    p_psMemSetDeallocator(metadataItem,(psFreeFcn)metadataItemFree);
-
+    p_psMemSetDeallocator( metadataItem, ( psFreeFcn ) metadataItemFree );
+    
     // Allocate and set metadata item comment
-    metadataItem->comment = (char *)psAlloc(sizeof(char)*MAX_STRING_LENGTH);
-    if(comment == NULL) {
-        // Per SDRS, null isn't allowed, must use "" instead
-        strncpy(metadataItem->comment, "", MAX_STRING_LENGTH);
-    } else {
-        strncpy(metadataItem->comment, comment, MAX_STRING_LENGTH);
-    }
-
-    // Set metadata item id
-    *(int*)(&metadataItem->id) = ++metadataId;
-
+    metadataItem->comment = ( char * ) psAlloc( sizeof( char ) * MAX_STRING_LENGTH );
+    if ( comment == NULL ) {
+            // Per SDRS, null isn't allowed, must use "" instead
+            strncpy( metadataItem->comment, "", MAX_STRING_LENGTH );
+        } else {
+            strncpy( metadataItem->comment, comment, MAX_STRING_LENGTH );
+        }
+        
+    // Set metadata item unique id
+    *( int* ) ( &metadataItem->id ) = ++metadataId;
+    
     // Set metadata item type
     metadataItem->type = type;
-
+    
     // Set metadata item value
-    switch(type) {
-    case PS_META_S32:
-        metadataItem->data.S32 = va_arg(argPtr, psS32);
-        break;
-    case PS_META_F32:
-        metadataItem->data.F32 = (psF32)va_arg(argPtr, psF64);
-        break;
-    case PS_META_F64:
-        metadataItem->data.F64 = va_arg(argPtr, psF64);
-        break;
-    case PS_META_STR:
-    case PS_META_IMG:
-    case PS_META_JPEG:
-    case PS_META_PNG:
-    case PS_META_ASTROM:
-    case PS_META_UNKNOWN:
-        metadataItem->data.V = psMemIncrRefCounter(va_arg(argPtr, psPTR));
-        break;
-    default:
-        psError(__func__, " Invalid psMetadataType: %d", type);
-    }
-
+    switch ( type ) {
+            case PS_META_S32:
+            metadataItem->data.S32 = va_arg( argPtr, psS32 );
+            break;
+            case PS_META_F32:
+            metadataItem->data.F32 = ( psF32 ) va_arg( argPtr, psF64 );
+            break;
+            case PS_META_F64:
+            metadataItem->data.F64 = va_arg( argPtr, psF64 );
+            break;
+            case PS_META_STR:
+            case PS_META_IMG:
+            case PS_META_JPEG:
+            case PS_META_PNG:
+            case PS_META_ASTROM:
+            case PS_META_UNKNOWN:
+            metadataItem->data.V = psMemIncrRefCounter( va_arg( argPtr, psPTR ) );
+            break;
+            default:
+            psError( __func__, " Invalid psMetadataType: %d", type );
+        }
+        
     // Allocate and set metadata item name
-    metadataItem->name = (char *)psAlloc(sizeof(char)*MAX_STRING_LENGTH);
-    vsprintf(metadataItem->name, name, argPtr);
-
+    metadataItem->name = ( char * ) psAlloc( sizeof( char ) * MAX_STRING_LENGTH );
+    vsprintf( metadataItem->name, name, argPtr );
+    
     // Allocate metadata items with same name.
-    metadataItem->items = psListAlloc(NULL);
-
+    metadataItem->items = psListAlloc( NULL );
+    
     return metadataItem;
 }
 
-psMetadata *psMetadataAlloc(void)
-{
-    psList *list = NULL;
+psMetadata *psMetadataAlloc( void )
+{
+    psList * list = NULL;
     psHash *table = NULL;
     psMetadata *metadata = NULL;
-
+    
     // Allocate metadata
-    metadata = (psMetadata *)psAlloc(sizeof(psMetadata));
-    if(metadata == NULL) {
-        psAbort(__func__,"Failed to allocate metadata");
-    }
-
+    metadata = ( psMetadata * ) psAlloc( sizeof( psMetadata ) );
+    if ( metadata == NULL ) {
+            psAbort( __func__, "Failed to allocate metadata" );
+        }
+        
     // Set deallocator
-    p_psMemSetDeallocator(metadata,(psFreeFcn)metadataFree);
-
+    p_psMemSetDeallocator( metadata, ( psFreeFcn ) metadataFree );
+    
     // Allocate internal containers
-    list = (psList *)psAlloc(sizeof(psList));
-    if(list == NULL) {
-        psAbort(__func__,"Failed to allocate list");
-    }
-
-    table = (psHash *)psAlloc(sizeof(psHash));
-    if(table == NULL) {
-        psAbort(__func__,"Failed to allocate table");
-    }
-
+    list = ( psList * ) psAlloc( sizeof( psList ) );
+    if ( list == NULL ) {
+            psAbort( __func__, "Failed to allocate list" );
+        }
+        
+    table = ( psHash * ) psAlloc( sizeof( psHash ) );
+    if ( table == NULL ) {
+            psAbort( __func__, "Failed to allocate table" );
+        }
+        
     return metadata;
 }
 
-bool psMetadataAddItem(psMetadata *restrict md, int where, psMetadataItem *restrict metadataItem)
-{
-    char *key = NULL;
+bool psMetadataAddItem( psMetadata *restrict md, int where, psMetadataItem *restrict metadataItem )
+{
+    char * key = NULL;
     psHash *mdTable = NULL;
     psList *mdList = NULL;
     psMetadataItem *value = NULL;
     psMetadataType type = PS_META_ITEM_SET;
-
-    if(md == NULL) {
-        psError(__func__, "Null metadata collection not allowed");
-        return false;
-    }
-
-    if(metadataItem == NULL) {
-        psError(__func__, "Null metadata item not allowed");
-        return false;
-    }
-
+    
+    if ( md == NULL ) {
+            psError( __func__, "Null metadata collection not allowed" );
+            return false;
+        }
+        
+    if ( metadataItem == NULL ) {
+            psError( __func__, "Null metadata item not allowed" );
+            return false;
+        }
+        
     type = metadataItem->type;
-
+    
     mdTable = md->table;
-    if(mdTable == NULL) {
-        psError(__func__, "Null metadata table not allowed");
-        return false;
-    }
-
-    mdList = md->list;
-    if(mdList == NULL) {
-        psError(__func__, "Null metadata list not allowed");
-        return false;
-    }
-
+    if ( mdTable == NULL ) {
+            psError( __func__, "Null metadata table not allowed" );
+            return false;
+        }
+        
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return false;
+        }
+        
     key = metadataItem->name;
-    if(key == NULL) {
-        psError(__func__, "Null key item not allowed");
-        return false;
-    }
-
+    if ( key == NULL ) {
+            psError( __func__, "Null key item not allowed" );
+            return false;
+        }
+        
     // Check if key is already in table
-    value = (psMetadataItem*)psHashLookup(mdTable, key);
-    if(value!=NULL && type!=PS_META_ITEM_SET) {
-
-        // The key was found and the new metadata item is a leaf node (its type isn't PS_META_ITEM_SET), so
-        // add the new metadata item to hash as a child of the existing metadata item folder node.
-        if(!psListAdd(value->items, metadataItem, where)) {
-            psError(__func__, "Couldn't add metadata item to items list. Name: %s",
-                    metadataItem->name);
-            return false;
-        }
-    } else if(value != NULL) {
-
-        // The key was found and the new metadata item is a folder node. Don't add new metadata item, since
-        // it will wipe out existing node.
-        psError(__func__, "Metadata already exists in metadata collection. Item not added. Name: %s",
-                metadataItem->name);
-        return false;
-    } else {
-
-        // Duplicate key not found. Add new metadata item to metadata collection's hash
-        if(!psHashAdd(mdTable, key, metadataItem)) {
-            psError(__func__, "Couldn't add metadata item to metadata collection table. Name: %s",
-                    metadataItem->name);
-            return false;
-        }
-    }
-
+    value = ( psMetadataItem* ) psHashLookup( mdTable, key );
+    if ( value != NULL && type != PS_META_ITEM_SET ) {
+    
+            // The key was found and the new metadata item is a leaf node (its type isn't PS_META_ITEM_SET), so
+            // add the new metadata item to hash as a child of the existing metadata item folder node.
+            if ( !psListAdd( value->items, metadataItem, where ) ) {
+                    psError( __func__, "Couldn't add metadata item to items list. Name: %s",
+                             metadataItem->name );
+                    return false;
+                }
+        } else if ( value != NULL ) {
+        
+            // The key was found and the new metadata item is a folder node. Don't add new metadata item, since
+            // it will wipe out existing node.
+            psError( __func__, "Metadata already exists in metadata collection. Item not added. Name: %s",
+                     metadataItem->name );
+            return false;
+        } else {
+        
+            // Duplicate key not found. Add new metadata item to metadata collection's hash
+            if ( !psHashAdd( mdTable, key, metadataItem ) ) {
+                    psError( __func__, "Couldn't add metadata item to metadata collection table. Name: %s",
+                             metadataItem->name );
+                    return false;
+                }
+        }
+        
     // Add all items to metadata collection's list, even if they have the same metadata item names
-    if(!psListAdd(md->list, metadataItem, where)) {
-        psError(__func__, "Couldn't add metadata item to metadata collection list. Name: %s",
-                metadataItem->name);
-        return false;
-    }
-
+    if ( !psListAdd( md->list, metadataItem, where ) ) {
+            psError( __func__, "Couldn't add metadata item to metadata collection list. Name: %s",
+                     metadataItem->name );
+            return false;
+        }
+        
     return true;
 }
 
-bool psMetadataAdd(psMetadata *restrict md, int where, const char *name, psMetadataType type,
-                   const char *comment, ...)
+bool psMetadataAdd( psMetadata *restrict md, int where, const char *name, psMetadataType type,
+                    const char *comment, ... )
 {
     va_list argPtr;
     psMetadataItem *metadataItem = NULL;
-
-    va_start(argPtr, comment);
-    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
-    va_end(argPtr);
-
-    return psMetadataAddItem(md, where, metadataItem);
-}
-
-/** Remove an item from metadata collection.
- *
- * Items may be removed from metadata by specifing a key or location. If the key is null, the where argument
- * is used instead. If name is not null, where is set to PS_LIST_UNKNOWN. If the item is found, it is removed
- * from the metadata and true is returned.  If the key is not unique, then all items corresponding to it are
- * removed.
- *
- * @return bool: True for success, false for failure.
- */
-bool psMetadataRemove(psMetadata *restrict md, int where, const char *restrict key)
-{
-    /*    int i = 0;
-        int numChildren = 0;
-        psList mdList = NULL;
-        psHash mdHash = NULL;
-        psMetadataItem *entry = NULL;
-        psMetadataItem *entryChild = NULL;
-     
-        mdList = md->list
-        if(mdList == NULL) {
-            psError(__func__, "Null metadata list not allowed");
-            return false;
-        }
-     
-        mdTable = md->table;
-        if(mdTable == NULL) {
-            psError(__func__, "Null metadata table not allowed");
-            return false;
-        }
-     
-        // Select removal by key or index
-        if(key != NULL){
-     
+    
+    va_start( argPtr, comment );
+    metadataItem = psMetadataItemAllocV( name, type, comment, argPtr );
+    va_end( argPtr );
+    
+    if ( !psMetadataAddItem( md, where, metadataItem ) ) {
+            psError( __func__, "Couldn't add metadata item to metadata collection list. Name: %s",
+                     metadataItem->name );
+            psFree( metadataItem );
+            return false;
+        }
+        
+    return true;
+}
+
+bool psMetadataRemove( psMetadata *restrict md, int where, const char *restrict key )
+{
+    int numChildren = 0;
+    psList *mdList = NULL;
+    psHash *mdTable = NULL;
+    psMetadataItem *entry = NULL;
+    psMetadataItem *entryChild = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return false;
+        }
+        
+    mdTable = md->table;
+    if ( mdTable == NULL ) {
+            psError( __func__, "Null metadata table not allowed" );
+            return false;
+        }
+        
+    // Select removal by key or index
+    if ( key != NULL ) {
+    
             // Remove by key name
-            entry = (psMetadataItem*)psHashLookup(mdTable, key);
-            if(entry == NULL) {
-                psError(__func__, "Couldn't find metadata item remove. Name: %s", key);
-                return false;
-            }
-     
+            entry = ( psMetadataItem* ) psHashLookup( mdTable, key );
+            if ( entry == NULL ) {
+                    psError( __func__, "Couldn't find metadata item remove. Name: %s", key );
+                    return false;
+                }
+                
             numChildren = entry->items->size;
-            if(entry->type==PS_META_ITEM_SET && numChildren>0){
-     
-                // Table entry has children. Entry and children must be removed from metadata collection's list
-                psListSetIterator(list, PS_LIST_HEAD);
-                entryChild = psListGetCurrent(list);
-                while (entryChild != NULL) {
-                    if(!psListRemove(mdList, entry, PS_LIST_UNKNOWN)) {
-                        psError(__func__, "Couldn't remove metadata item from list. Name: %s", key);
-                        return false;
-                    }
-                }
-                entryChild = psListGetNext(list);
-            } else {
-     
-                // Table entry does not have children. Entry only must be removed from metadata collection's list
-                if(!psListRemove(mdList, entry, PS_LIST_UNKNOWN)) {
-                    psError(__func__, "Couldn't remove metadata item from list. Name: %s", key);
+            if ( entry->type == PS_META_ITEM_SET && numChildren > 0 ) {
+            
+                    // Table entry has children. Entry and children must be removed from metadata collection's list
+                    psListSetIterator( mdList, PS_LIST_HEAD );
+                    entryChild = psListGetCurrent( mdList );
+                    while ( entryChild != NULL ) {
+                            if ( !psListRemove( entry->items, entryChild, PS_LIST_UNKNOWN ) ) {
+                                    psError( __func__, "Couldn't remove metadata item from list. Name: %s", key );
+                                    return false;
+                                }
+                            entryChild = psListGetNext( entry->items );
+                        }
+                }
+                
+            // Remove entry from metadata collection's list
+            if ( !psListRemove( mdList, entry, PS_LIST_UNKNOWN ) ) {
+                    psError( __func__, "Couldn't remove metadata item from list. Name: %s", key );
                     return false;
                 }
-     
-            }
-     
-            // Remove entry from table once duplictes have been removed from the metadata collection's list
-            if(!psHashRemove(mdHash, key)) {
-                psError(__func__, "Couldn't remove metadata item from table. Name: %s", key);
-                return false;
-            }
+                
+            // Remove entry from metadata collection's table
+            if ( !psHashRemove( mdTable, key ) ) {
+                    psError( __func__, "Couldn't remove metadata item from table. Name: %s", key );
+                    return false;
+                }
         } else {
+        
             // Remove by index
-     
-        }*/
-
+            entry = psListGet( mdList, where );
+            if ( entry == NULL ) {
+                    psError( __func__, "Couldn't find metadata item from list. Index: %d", where );
+                    return false;
+                }
+                
+            key = entry->name;
+            if ( key == NULL ) {
+                    psError( __func__, "Null key name not allowed. Index: %d", where );
+                    return false;
+                }
+                
+            // Use recursive remove, now that key is known
+            psMetadataRemove( md, PS_LIST_UNKNOWN, key );
+        }
+        
     return true;
 }
 
+psMetadataItem *psMetadataLookup( psMetadata *restrict md, const char *restrict key )
+{
+    psHash * mdTable = NULL;
+    psMetadataItem *entry = NULL;
+    
+    mdTable = md->table;
+    if ( mdTable == NULL ) {
+            psError( __func__, "Null metadata table not allowed" );
+            return NULL;
+        }
+        
+    if ( key == NULL ) {
+            psError( __func__, "Null key name not allowed" );
+            return NULL;
+        }
+        
+    entry = ( psMetadataItem* ) psHashLookup( mdTable, key );
+    if ( entry == NULL ) {
+            psError( __func__, "Could not find metadata item with given key. Key: %s", key );
+            return NULL;
+        }
+        
+    return entry;
+}
+
+psMetadataItem *psMetadataGet( psMetadata *restrict md, int where )
+{
+    psList * mdList = NULL;
+    psMetadataItem *entry = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    entry = ( psMetadataItem* ) psListGet( mdList, where );
+    if ( entry == NULL ) {
+            psError( __func__, "Couldn't find metadata item with given index. Index: %d", where );
+            return NULL;
+        }
+        
+    return entry;
+}
+
+bool psMetadataSetIterator( psMetadata *restrict md, int where )
+{
+    psList * mdList = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return false;
+        }
+        
+    psListSetIterator( mdList, where );
+    
+    return true;
+}
+
+psMetadataItem *psMetadataGetNext( psMetadata *restrict md, const char *restrict match, int which )
+{
+    psList * mdList = NULL;
+    psMetadataItem *entry = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    psListSetIterator( mdList, which );
+    entry = psListGetCurrent( mdList );
+    while ( entry != NULL ) {
+            if ( !strncmp( match, entry->name, strlen( match ) ) ) {
+            
+                    // Match found
+                    return entry;
+                }
+            entry = psListGetNext( mdList );
+        }
+        
+    // Match not found
+    if ( entry == NULL ) {
+            psError( __func__, "Couldn't find metadata item with given match. Match: %s", match );
+        }
+        
+    return entry;
+}
+
+psMetadataItem *psMetadataGetPrevious( psMetadata *restrict md, const char *restrict match, int which )
+{
+    psList * mdList = NULL;
+    psMetadataItem *entry = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    psListSetIterator( mdList, which );
+    entry = psListGetCurrent( mdList );
+    while ( entry != NULL ) {
+            if ( !strncmp( match, entry->name, strlen( match ) ) ) {
+            
+                    // Match found
+                    return entry;
+                }
+            entry = psListGetPrevious( mdList );
+        }
+        
+    // Match not found
+    if ( entry == NULL ) {
+            psError( __func__, "Couldn't find metadata item with given match. Match: %s", match );
+        }
+        
+    return entry;
+}
+
+void psMetadataItemPrint( FILE *fd, const char *format, const psMetadataItem *restrict metadataItem )
+{
+    psMetadataType type;
+    
+    if ( fd == NULL ) {
+            psError( __func__, "Null file descriptor not allowed" );
+            return ;
+        }
+        
+    if ( format == NULL ) {
+            psError( __func__, "Null format not allowed" );
+            return ;
+        }
+        
+    if ( metadataItem == NULL ) {
+            psError( __func__, "Null metadata not allowed" );
+            return ;
+        }
+        
+    type = metadataItem->type;
+    
+    switch ( type ) {
+            case PS_META_S32:
+            fprintf( fd, format, metadataItem->data.S32 );
+            break;
+            case PS_META_F32:
+            fprintf( fd, format, metadataItem->data.F32 );
+            break;
+            case PS_META_F64:
+            fprintf( fd, format, metadataItem->data.F64 );
+            break;
+            case PS_META_STR:
+            fprintf( fd, format, metadataItem->data.V );
+            break;
+            case PS_META_ITEM_SET:
+            case PS_META_IMG:
+            case PS_META_JPEG:
+            case PS_META_PNG:
+            case PS_META_ASTROM:
+            case PS_META_UNKNOWN:
+            default:
+            psError( __func__, " Invalid psMetadataType to print: %d", type );
+        }
+}
+
+psMetadata *psMetadataReadHeader( psMetadata *output, const char *extname, int extnum, const char *filename )
+{
+    return NULL;
+    
+}
+
+psMetadata *psMetadataFReadHeader( psMetadata *output, const char *extname, int extnum, fitsfile *fd )
+{
+    bool success;
+    char keyType;
+    char keyName[ MAX_VAL_SIZE ];
+    char keyValue[ MAX_VAL_SIZE ];
+    char keyComment[ MAX_VAL_SIZE ];
+    char fitsErr[ MAX_ERR_MESSAGE_LENGTH ];
+    char* tempExtname = NULL;
+    int i;
+    int hduType = 0;
+    int status = 0;
+    int numKeys = 0;
+    psMetadataType metadataItemType;
+    
+    if ( fd == NULL ) {
+            psError( __func__, "Null FITS file descriptor not allowed" );
+            return NULL;
+        }
+        
+    if ( extname == NULL && extnum == 0 ) {
+            psError( __func__, "Null extname AND extnum = 0 not allowed" );
+            return NULL;
+        } else if ( extname && extnum ) {
+            psError( __func__, "Both extname AND extnum arguments should not have valid values." );
+            return NULL;
+        }
+        
+    // Allocate metadata if user didn't
+    if ( output == NULL ) {
+            output = psMetadataAlloc();
+            return NULL;
+        }
+        
+    // Move to user designated HDU number or HDU name in FITS file. HDU numbers starts at one.
+    if ( extname == NULL ) {
+            if ( fits_movabs_hdu( fd, extnum, &hduType, &status ) != 0 ) {
+                    fits_get_errstatus( status, fitsErr );
+                    psError( __func__, "FITS error while locating header: %s", fitsErr );
+                    status = 0;
+                    fits_close_file( fd, &status );
+                    return NULL;
+                }
+        } else if ( extnum > 0 ) {
+            tempExtname = ( char* ) psAlloc( strlen( extname ) + 1 ); // fits_movnam_hdu doesn't like const part of extname
+            strncpy( tempExtname, extname, MAX_VAL_SIZE );
+            if ( fits_movnam_hdu( fd, ANY_HDU, tempExtname, 0, &status ) != 0 ) {
+                    fits_get_errstatus( status, fitsErr );
+                    psError( __func__, "FITS error while locating header: %s", fitsErr );
+                    status = 0;
+                    fits_close_file( fd, &status );
+                    psFree( tempExtname );
+                    return NULL;
+                }
+            psFree( tempExtname );
+        }
+        
+    // Get number of key names
+    if ( fits_get_hdrpos( fd, &numKeys, NULL, &status ) != 0 ) {
+            fits_get_errstatus( status, fitsErr );
+            psError( __func__, "FITS error while reading keys: %s", fitsErr );
+            status = 0;
+            fits_close_file( fd, &status );
+            return NULL;
+        }
+        
+    // Get each key name. Keywords start at one.
+    for ( i = 1; i <= numKeys; i++ ) {
+            if ( fits_read_keyn( fd, i, keyName, keyValue, keyComment, &status ) != 0 ) {
+                    fits_get_errstatus( status, fitsErr );
+                    psError( __func__, "FITS error while reading key number %d: %s", i, fitsErr );
+                    status = 0;
+                    fits_close_file( fd, &status );
+                    return NULL;
+                }
+                
+            if ( fits_get_keytype( keyValue, &keyType, &status ) != 0 ) {
+                    fits_get_errstatus( status, fitsErr );
+                    psError( __func__, "FITS error while determining key type: %s", fitsErr );
+                    status = 0;
+                    fits_close_file( fd, &status );
+                    return NULL;
+                }
+                
+            switch ( keyType ) {
+                    case 'I':
+                    metadataItemType = PS_META_S32;
+                    success = psMetadataAdd( output, PS_LIST_HEAD, keyName, metadataItemType, keyComment, atoi( keyValue ) );
+                    break;
+                    case 'F':
+                    metadataItemType = PS_META_F64;
+                    success = psMetadataAdd( output, PS_LIST_HEAD, keyName, metadataItemType, keyComment, atof( keyValue ) );
+                    break;
+                    case 'C':
+                    metadataItemType = PS_META_STR;
+                    success = psMetadataAdd( output, PS_LIST_HEAD, keyName, metadataItemType, keyComment, keyValue );
+                    break;
+                    case 'L':
+                    case 'X':
+                    default:
+                    psError( __func__, "Invalid psMetadataType: %c", keyType );
+                    return NULL;
+                }
+                
+            if ( !success ) {
+                    psError( __func__, "Failed to add metadata item. Name: %s", keyName );
+                }
+        }
+        
+    return output;
+}
Index: /trunk/psLib/src/astronomy/psMetadata.h
===================================================================
--- /trunk/psLib/src/astronomy/psMetadata.h	(revision 1350)
+++ /trunk/psLib/src/astronomy/psMetadata.h	(revision 1351)
@@ -1,18 +1,18 @@
 /** @file  psMetadata.h
- *
- *  @brief Contains metadata struuctures, enumerations and functions prototypes
- *
- *  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
- *  prototypes necessary creating psLib metadata APIs
- *
- *  @ingroup Metadata
- *
- *  @author Ross Harman, MHPCC
- *
- *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-07-29 20:16:34 $
- *
- *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
- */
+*
+*  @brief Contains metadata struuctures, enumerations and functions prototypes
+*
+*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+*  prototypes necessary creating psLib metadata APIs
+*
+*  @ingroup Metadata
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-07-30 19:37:07 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
 #ifndef PS_METADATA_H
 #define PS_METADATA_H
@@ -30,14 +30,14 @@
  */
 typedef enum {
-    PS_META_ITEM_SET = 0,               ///< Null. Metadata is in psMetadataItem.items
-    PS_META_S32,                        ///< Signed 32-bit integer data.
-    PS_META_F32,                        ///< Single-precision float data.
-    PS_META_F64,                        ///< Double-precision float data.
-    PS_META_STR,                        ///< String data (Stored in as void *).
-    PS_META_IMG,                        ///< Image data (Stored in as void *).
-    PS_META_JPEG,                       ///< JPEG data (Stored in as void .
-    PS_META_PNG,                        ///< PNG data (Stored in as void *).
-    PS_META_ASTROM,                     ///< Astrometric coefficients (Stored in as void *).
-    PS_META_UNKNOWN,                    ///< Other data (Stored in as void *).
+    PS_META_ITEM_SET = 0,                ///< Null. Metadata is in psMetadataItem.items
+    PS_META_S32,                         ///< Signed 32-bit integer data.
+    PS_META_F32,                         ///< Single-precision float data.
+    PS_META_F64,                         ///< Double-precision float data.
+    PS_META_STR,                         ///< String data (Stored in as void *).
+    PS_META_IMG,                         ///< Image data (Stored in as void *).
+    PS_META_JPEG,                        ///< JPEG data (Stored in as void .
+    PS_META_PNG,                         ///< PNG data (Stored in as void *).
+    PS_META_ASTROM,                      ///< Astrometric coefficients (Stored in as void *).
+    PS_META_UNKNOWN,                     ///< Other data (Stored in as void *).
     PS_META_NTYPE                       ///< Number of types. Must be last.
 } psMetadataType;
@@ -49,18 +49,18 @@
  */
 typedef struct psMetadataItem
-{
-    const int id;                       ///< Unique ID for metadata item.
-    char *restrict name;                ///< Name of metadata item.
-    psMetadataType type;                ///< Type of metadata item.
-    union
     {
-        psS32   S32;                    ///< Signed 32-bit integer data.
-        psF32   F32;                    ///< Single-precision float data.
-        psF64   F64;                    ///< Double-precision float data.
-        psPTR     V;                    ///< Pointer to other type of data.
-    }data;                              ///< Union for data types.
-    char *comment;                      ///< Optional comment ("", not NULL).
-    psList *restrict items;             ///< List of psMetadataItems with same name.
-}
+        const int id;                       ///< Unique ID for metadata item.
+        char *restrict name;                ///< Name of metadata item.
+        psMetadataType type;                ///< Type of metadata item.
+        union
+            {
+                psS32 S32;                    ///< Signed 32-bit integer data.
+                psF32 F32;                    ///< Single-precision float data.
+                psF64 F64;                    ///< Double-precision float data.
+                psPTR V;                    ///< Pointer to other type of data.
+            }data;                              ///< Union for data types.
+        char *comment;                      ///< Optional comment ("", not NULL).
+        psList *restrict items;             ///< List of psMetadataItems with same name.
+    }
 psMetadataItem;
 
@@ -72,8 +72,8 @@
  */
 typedef struct psMetadata
-{
-    psList *restrict list;
-    psHash *restrict table;
-}
+    {
+        psList *restrict list;
+        psHash *restrict table;
+    }
 psMetadata;
 
@@ -97,7 +97,7 @@
  */
 psMetadataItem *psMetadataItemAlloc(
-    const char *name,                   ///< Name of metadata item.
-    psMetadataType type,                ///< Type of metadata item.
-    const char *comment,                ///< Comment for metadata item.
+    const char *name,                    ///< Name of metadata item.
+    psMetadataType type,                 ///< Type of metadata item.
+    const char *comment,                 ///< Comment for metadata item.
     ...                                 ///< Arguments for name formatting and metadata item data.
 );
@@ -117,7 +117,7 @@
  */
 psMetadataItem *psMetadataItemAllocV(
-    const char *name,                   ///< Name of metadata item.
-    psMetadataType type,                ///< Type of metadata item.
-    const char *comment,                ///< Comment for metadata item.
+    const char *name,                    ///< Name of metadata item.
+    psMetadataType type,                 ///< Type of metadata item.
+    const char *comment,                 ///< Comment for metadata item.
     va_list list                        ///< Arguments for name formatting and metadata item data.
 );
@@ -140,6 +140,6 @@
  */
 bool psMetadataAddItem(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
-    int where,                          ///< Location to be added.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
+    int where,                           ///< Location to be added.
     psMetadataItem *restrict item       ///< Metadata item to be added.
 );
@@ -152,9 +152,9 @@
  */
 bool psMetadataAdd(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
-    int where,                          ///< Location to be added.
-    const char *name,                   ///< Name of metadata item.
-    psMetadataType type,                ///< Type of metadata item.
-    const char *comment,                ///< Comment for metadata item.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
+    int where,                           ///< Location to be added.
+    const char *name,                    ///< Name of metadata item.
+    psMetadataType type,                 ///< Type of metadata item.
+    const char *comment,                 ///< Comment for metadata item.
     ...                                 ///< Arguments for name formatting and metadata item data.
 );
@@ -170,6 +170,6 @@
  */
 bool psMetadataRemove(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
-    int where,                          ///< Location to be removed.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
+    int where,                           ///< Location to be removed.
     const char *restrict key            ///< Name of metadata key.
 );
@@ -183,5 +183,5 @@
  */
 psMetadataItem *psMetadataLookup(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
     const char *restrict key            ///< Name of metadata key.
 );
@@ -194,5 +194,5 @@
  */
 psMetadataItem *psMetadataGet(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
     int where                           ///< Location to be retrieved.
 );
@@ -205,5 +205,5 @@
  */
 bool psMetadataSetIterator(
-    psMetadata *restrict md,            ///< Metadata collection to iterate.
+    psMetadata *restrict md,             ///< Metadata collection to iterate.
     int where                           ///< Location of iterator.
 );
@@ -216,6 +216,6 @@
  */
 psMetadataItem *psMetadataGetNext(
-    psMetadata *restrict md,            ///< Metadata collection to iterate.
-    const char *restrict match,         ///< Beginning of key name.
+    psMetadata *restrict md,             ///< Metadata collection to iterate.
+    const char *restrict match,          ///< Beginning of key name.
     int which                           ///< Iterator to be used.
 );
@@ -228,6 +228,6 @@
  */
 psMetadataItem *psMetadataGetPrevious(
-    psMetadata *restrict md,            ///< Metadata collection to iterate.
-    const char *restrict match,         ///< Beginning of key name.
+    psMetadata *restrict md,             ///< Metadata collection to iterate.
+    const char *restrict match,          ///< Beginning of key name.
     int which                           ///< Iterator to be used.
 );
@@ -244,7 +244,7 @@
  */
 void psMetadataItemPrint(
-    FILE *fd,                           ///< Pointer to file to write metadata item.
-    const char *format,                 ///< Format to print metadata item.
-    const psMetadataItem *restrict md   ///< Metadata item to print.
+    FILE *fd,                                    ///< Pointer to file to write metadata item.
+    const char *format,                          ///< Format to print metadata item.
+    const psMetadataItem *restrict metadataItem ///< Metadata item to print.
 );
 
@@ -256,7 +256,7 @@
  */
 psMetadata *psMetadataReadHeader(
-    psMetadata *output,                 ///< Resulting metadata from read.
-    const char *extname,                ///< File name extension string.
-    int extnum,                         ///< File name extension number.
+    psMetadata *output,                  ///< Resulting metadata from read.
+    const char *extname,                 ///< File name extension string.
+    int extnum,                          ///< File name extension number.
     const char *filename                ///< Name of file to read.
 );
@@ -269,8 +269,8 @@
  */
 psMetadata *psMetadataFReadHeader(
-    psMetadata *output,                 ///< Resulting metadata from read.
-    const char *extname,                ///< File name extension string.
-    int extnum,                         ///< File name extension number.
-    FILE *fd                            ///< Pointer to file to read.
+    psMetadata *output,                  ///< Resulting metadata from read.
+    const char *extname,                 ///< File name extension string.
+    int extnum,                          ///< File name extension number.
+    fitsfile *fd                        ///< Pointer to file to read.
 );
 /// @}
Index: /trunk/psLib/src/collections/psMetadata.c
===================================================================
--- /trunk/psLib/src/collections/psMetadata.c	(revision 1350)
+++ /trunk/psLib/src/collections/psMetadata.c	(revision 1351)
@@ -1,19 +1,19 @@
 /** @file  psMetadata.c
- *
- *
- *  @brief Contains metadata struuctures, enumerations and functions prototypes
- *
- *  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
- *  prototypes necessary creating psLib metadata APIs
- *
- *  @ingroup Metadata
- *
- *  @author Ross Harman, MHPCC
- *
- *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-07-29 02:04:20 $
- *
- *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
- */
+*
+*
+*  @brief Contains metadata struuctures, enumerations and functions prototypes
+*
+*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+*  prototypes necessary creating psLib metadata APIs
+*
+*  @ingroup Metadata
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-07-30 19:36:52 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
 
 /******************************************************************************/
@@ -24,4 +24,5 @@
 #include<string.h>
 
+#include "fitsio.h"
 #include "psType.h"
 #include "psMemory.h"
@@ -37,5 +38,9 @@
 /******************************************************************************/
 
-// None
+// Maximum metadata length string
+#define MAX_VAL_SIZE 1024
+
+// Maximum metadata error length
+#define MAX_ERR_MESSAGE_LENGTH 1024
 
 /******************************************************************************/
@@ -60,33 +65,33 @@
 /*  FUNCTION IMPLEMENTATION - LOCAL                                          */
 /*****************************************************************************/
-static void metadataItemFree(psMetadataItem *metadataItem)
+static void metadataItemFree( psMetadataItem *metadataItem )
 {
     psMetadataType type;
-
+    
     type = metadataItem->type;
-
-    if (metadataItem == NULL) {
-        return;
-    }
-
-    psFree(metadataItem->name);
-    psFree(metadataItem->comment);
-
-    if(type==PS_META_STR || type==PS_META_IMG || type==PS_META_JPEG || type==PS_META_PNG ||
-            type==PS_META_ASTROM || type==PS_META_UNKNOWN) {
-        psFree(metadataItem->data.V);
-    }
-
-    psFree(metadataItem->items);
-}
-
-static void metadataFree(psMetadata *metadata)
-{
-    if (metadata == NULL) {
-        return;
-    }
-
-    psFree(metadata->list);
-    psFree(metadata->table);
+    
+    if ( metadataItem == NULL ) {
+            return ;
+        }
+        
+    psFree( metadataItem->name );
+    psFree( metadataItem->comment );
+    
+    if ( type == PS_META_STR || type == PS_META_IMG || type == PS_META_JPEG || type == PS_META_PNG ||
+            type == PS_META_ASTROM || type == PS_META_UNKNOWN ) {
+            psFree( metadataItem->data.V );
+        }
+        
+    psFree( metadataItem->items );
+}
+
+static void metadataFree( psMetadata *metadata )
+{
+    if ( metadata == NULL ) {
+            return ;
+        }
+        
+    psFree( metadata->list );
+    psFree( metadata->table );
 }
 
@@ -95,279 +100,582 @@
 /*****************************************************************************/
 
-psMetadataItem *psMetadataItemAlloc(const char *name, psMetadataType type, const char *comment, ...)
+psMetadataItem *psMetadataItemAlloc( const char *name, psMetadataType type, const char *comment, ... )
 {
     va_list argPtr;
     psMetadataItem *metadataItem = NULL;
-
+    
     // Get the variable list parameters to pass to allocation function
-    va_start(argPtr, comment);
-
+    va_start( argPtr, comment );
+    
     // Call metadata item allocation
-    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
-
+    metadataItem = psMetadataItemAllocV( name, type, comment, argPtr );
+    
     // Clean up stack after variable arguement has been used
-    va_end(argPtr);
-
+    va_end( argPtr );
+    
     return metadataItem;
 }
 
-psMetadataItem *psMetadataItemAllocV(const char *name, psMetadataType type, const char *comment, va_list argPtr)
-{
-    psMetadataItem *metadataItem = NULL;
-
-    if(name == NULL) {
-        psError(__func__, "Null value for string not allowed");
-        return NULL;
-    }
-
+psMetadataItem *psMetadataItemAllocV( const char *name, psMetadataType type, const char *comment, va_list argPtr )
+{
+    psMetadataItem * metadataItem = NULL;
+    
+    if ( name == NULL ) {
+            psError( __func__, "Null value for string not allowed" );
+            return NULL;
+        }
+        
     // Allocate metadata item
-    metadataItem = (psMetadataItem *)psAlloc(sizeof(psMetadataItem));
-    if(metadataItem == NULL) {
-        psAbort(__func__,"Failed to allocate memory");
-    }
-
+    metadataItem = ( psMetadataItem * ) psAlloc( sizeof( psMetadataItem ) );
+    if ( metadataItem == NULL ) {
+            psAbort( __func__, "Failed to allocate memory" );
+        }
+        
     // Set deallocator
-    p_psMemSetDeallocator(metadataItem,(psFreeFcn)metadataItemFree);
-
+    p_psMemSetDeallocator( metadataItem, ( psFreeFcn ) metadataItemFree );
+    
     // Allocate and set metadata item comment
-    metadataItem->comment = (char *)psAlloc(sizeof(char)*MAX_STRING_LENGTH);
-    if(comment == NULL) {
-        // Per SDRS, null isn't allowed, must use "" instead
-        strncpy(metadataItem->comment, "", MAX_STRING_LENGTH);
-    } else {
-        strncpy(metadataItem->comment, comment, MAX_STRING_LENGTH);
-    }
-
-    // Set metadata item id
-    *(int*)(&metadataItem->id) = ++metadataId;
-
+    metadataItem->comment = ( char * ) psAlloc( sizeof( char ) * MAX_STRING_LENGTH );
+    if ( comment == NULL ) {
+            // Per SDRS, null isn't allowed, must use "" instead
+            strncpy( metadataItem->comment, "", MAX_STRING_LENGTH );
+        } else {
+            strncpy( metadataItem->comment, comment, MAX_STRING_LENGTH );
+        }
+        
+    // Set metadata item unique id
+    *( int* ) ( &metadataItem->id ) = ++metadataId;
+    
     // Set metadata item type
     metadataItem->type = type;
-
+    
     // Set metadata item value
-    switch(type) {
-    case PS_META_S32:
-        metadataItem->data.S32 = va_arg(argPtr, psS32);
-        break;
-    case PS_META_F32:
-        metadataItem->data.F32 = (psF32)va_arg(argPtr, psF64);
-        break;
-    case PS_META_F64:
-        metadataItem->data.F64 = va_arg(argPtr, psF64);
-        break;
-    case PS_META_STR:
-    case PS_META_IMG:
-    case PS_META_JPEG:
-    case PS_META_PNG:
-    case PS_META_ASTROM:
-    case PS_META_UNKNOWN:
-        metadataItem->data.V = psMemIncrRefCounter(va_arg(argPtr, psPTR));
-        break;
-    default:
-        psError(__func__, " Invalid psMetadataType: %d", type);
-    }
-
+    switch ( type ) {
+            case PS_META_S32:
+            metadataItem->data.S32 = va_arg( argPtr, psS32 );
+            break;
+            case PS_META_F32:
+            metadataItem->data.F32 = ( psF32 ) va_arg( argPtr, psF64 );
+            break;
+            case PS_META_F64:
+            metadataItem->data.F64 = va_arg( argPtr, psF64 );
+            break;
+            case PS_META_STR:
+            case PS_META_IMG:
+            case PS_META_JPEG:
+            case PS_META_PNG:
+            case PS_META_ASTROM:
+            case PS_META_UNKNOWN:
+            metadataItem->data.V = psMemIncrRefCounter( va_arg( argPtr, psPTR ) );
+            break;
+            default:
+            psError( __func__, " Invalid psMetadataType: %d", type );
+        }
+        
     // Allocate and set metadata item name
-    metadataItem->name = (char *)psAlloc(sizeof(char)*MAX_STRING_LENGTH);
-    vsprintf(metadataItem->name, name, argPtr);
-
+    metadataItem->name = ( char * ) psAlloc( sizeof( char ) * MAX_STRING_LENGTH );
+    vsprintf( metadataItem->name, name, argPtr );
+    
     // Allocate metadata items with same name.
-    metadataItem->items = psListAlloc(NULL);
-
+    metadataItem->items = psListAlloc( NULL );
+    
     return metadataItem;
 }
 
-psMetadata *psMetadataAlloc(void)
-{
-    psList *list = NULL;
+psMetadata *psMetadataAlloc( void )
+{
+    psList * list = NULL;
     psHash *table = NULL;
     psMetadata *metadata = NULL;
-
+    
     // Allocate metadata
-    metadata = (psMetadata *)psAlloc(sizeof(psMetadata));
-    if(metadata == NULL) {
-        psAbort(__func__,"Failed to allocate metadata");
-    }
-
+    metadata = ( psMetadata * ) psAlloc( sizeof( psMetadata ) );
+    if ( metadata == NULL ) {
+            psAbort( __func__, "Failed to allocate metadata" );
+        }
+        
     // Set deallocator
-    p_psMemSetDeallocator(metadata,(psFreeFcn)metadataFree);
-
+    p_psMemSetDeallocator( metadata, ( psFreeFcn ) metadataFree );
+    
     // Allocate internal containers
-    list = (psList *)psAlloc(sizeof(psList));
-    if(list == NULL) {
-        psAbort(__func__,"Failed to allocate list");
-    }
-
-    table = (psHash *)psAlloc(sizeof(psHash));
-    if(table == NULL) {
-        psAbort(__func__,"Failed to allocate table");
-    }
-
+    list = ( psList * ) psAlloc( sizeof( psList ) );
+    if ( list == NULL ) {
+            psAbort( __func__, "Failed to allocate list" );
+        }
+        
+    table = ( psHash * ) psAlloc( sizeof( psHash ) );
+    if ( table == NULL ) {
+            psAbort( __func__, "Failed to allocate table" );
+        }
+        
     return metadata;
 }
 
-bool psMetadataAddItem(psMetadata *restrict md, int where, psMetadataItem *restrict metadataItem)
-{
-    char *key = NULL;
+bool psMetadataAddItem( psMetadata *restrict md, int where, psMetadataItem *restrict metadataItem )
+{
+    char * key = NULL;
     psHash *mdTable = NULL;
     psList *mdList = NULL;
     psMetadataItem *value = NULL;
     psMetadataType type = PS_META_ITEM_SET;
-
-    if(md == NULL) {
-        psError(__func__, "Null metadata collection not allowed");
-        return false;
-    }
-
-    if(metadataItem == NULL) {
-        psError(__func__, "Null metadata item not allowed");
-        return false;
-    }
-
+    
+    if ( md == NULL ) {
+            psError( __func__, "Null metadata collection not allowed" );
+            return false;
+        }
+        
+    if ( metadataItem == NULL ) {
+            psError( __func__, "Null metadata item not allowed" );
+            return false;
+        }
+        
     type = metadataItem->type;
-
+    
     mdTable = md->table;
-    if(mdTable == NULL) {
-        psError(__func__, "Null metadata table not allowed");
-        return false;
-    }
-
-    mdList = md->list;
-    if(mdList == NULL) {
-        psError(__func__, "Null metadata list not allowed");
-        return false;
-    }
-
+    if ( mdTable == NULL ) {
+            psError( __func__, "Null metadata table not allowed" );
+            return false;
+        }
+        
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return false;
+        }
+        
     key = metadataItem->name;
-    if(key == NULL) {
-        psError(__func__, "Null key item not allowed");
-        return false;
-    }
-
+    if ( key == NULL ) {
+            psError( __func__, "Null key item not allowed" );
+            return false;
+        }
+        
     // Check if key is already in table
-    value = (psMetadataItem*)psHashLookup(mdTable, key);
-    if(value!=NULL && type!=PS_META_ITEM_SET) {
-
-        // The key was found and the new metadata item is a leaf node (its type isn't PS_META_ITEM_SET), so
-        // add the new metadata item to hash as a child of the existing metadata item folder node.
-        if(!psListAdd(value->items, metadataItem, where)) {
-            psError(__func__, "Couldn't add metadata item to items list. Name: %s",
-                    metadataItem->name);
-            return false;
-        }
-    } else if(value != NULL) {
-
-        // The key was found and the new metadata item is a folder node. Don't add new metadata item, since
-        // it will wipe out existing node.
-        psError(__func__, "Metadata already exists in metadata collection. Item not added. Name: %s",
-                metadataItem->name);
-        return false;
-    } else {
-
-        // Duplicate key not found. Add new metadata item to metadata collection's hash
-        if(!psHashAdd(mdTable, key, metadataItem)) {
-            psError(__func__, "Couldn't add metadata item to metadata collection table. Name: %s",
-                    metadataItem->name);
-            return false;
-        }
-    }
-
+    value = ( psMetadataItem* ) psHashLookup( mdTable, key );
+    if ( value != NULL && type != PS_META_ITEM_SET ) {
+    
+            // The key was found and the new metadata item is a leaf node (its type isn't PS_META_ITEM_SET), so
+            // add the new metadata item to hash as a child of the existing metadata item folder node.
+            if ( !psListAdd( value->items, metadataItem, where ) ) {
+                    psError( __func__, "Couldn't add metadata item to items list. Name: %s",
+                             metadataItem->name );
+                    return false;
+                }
+        } else if ( value != NULL ) {
+        
+            // The key was found and the new metadata item is a folder node. Don't add new metadata item, since
+            // it will wipe out existing node.
+            psError( __func__, "Metadata already exists in metadata collection. Item not added. Name: %s",
+                     metadataItem->name );
+            return false;
+        } else {
+        
+            // Duplicate key not found. Add new metadata item to metadata collection's hash
+            if ( !psHashAdd( mdTable, key, metadataItem ) ) {
+                    psError( __func__, "Couldn't add metadata item to metadata collection table. Name: %s",
+                             metadataItem->name );
+                    return false;
+                }
+        }
+        
     // Add all items to metadata collection's list, even if they have the same metadata item names
-    if(!psListAdd(md->list, metadataItem, where)) {
-        psError(__func__, "Couldn't add metadata item to metadata collection list. Name: %s",
-                metadataItem->name);
-        return false;
-    }
-
+    if ( !psListAdd( md->list, metadataItem, where ) ) {
+            psError( __func__, "Couldn't add metadata item to metadata collection list. Name: %s",
+                     metadataItem->name );
+            return false;
+        }
+        
     return true;
 }
 
-bool psMetadataAdd(psMetadata *restrict md, int where, const char *name, psMetadataType type,
-                   const char *comment, ...)
+bool psMetadataAdd( psMetadata *restrict md, int where, const char *name, psMetadataType type,
+                    const char *comment, ... )
 {
     va_list argPtr;
     psMetadataItem *metadataItem = NULL;
-
-    va_start(argPtr, comment);
-    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
-    va_end(argPtr);
-
-    return psMetadataAddItem(md, where, metadataItem);
-}
-
-/** Remove an item from metadata collection.
- *
- * Items may be removed from metadata by specifing a key or location. If the key is null, the where argument
- * is used instead. If name is not null, where is set to PS_LIST_UNKNOWN. If the item is found, it is removed
- * from the metadata and true is returned.  If the key is not unique, then all items corresponding to it are
- * removed.
- *
- * @return bool: True for success, false for failure.
- */
-bool psMetadataRemove(psMetadata *restrict md, int where, const char *restrict key)
-{
-    /*    int i = 0;
-        int numChildren = 0;
-        psList mdList = NULL;
-        psHash mdHash = NULL;
-        psMetadataItem *entry = NULL;
-        psMetadataItem *entryChild = NULL;
-     
-        mdList = md->list
-        if(mdList == NULL) {
-            psError(__func__, "Null metadata list not allowed");
-            return false;
-        }
-     
-        mdTable = md->table;
-        if(mdTable == NULL) {
-            psError(__func__, "Null metadata table not allowed");
-            return false;
-        }
-     
-        // Select removal by key or index
-        if(key != NULL){
-     
+    
+    va_start( argPtr, comment );
+    metadataItem = psMetadataItemAllocV( name, type, comment, argPtr );
+    va_end( argPtr );
+    
+    if ( !psMetadataAddItem( md, where, metadataItem ) ) {
+            psError( __func__, "Couldn't add metadata item to metadata collection list. Name: %s",
+                     metadataItem->name );
+            psFree( metadataItem );
+            return false;
+        }
+        
+    return true;
+}
+
+bool psMetadataRemove( psMetadata *restrict md, int where, const char *restrict key )
+{
+    int numChildren = 0;
+    psList *mdList = NULL;
+    psHash *mdTable = NULL;
+    psMetadataItem *entry = NULL;
+    psMetadataItem *entryChild = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return false;
+        }
+        
+    mdTable = md->table;
+    if ( mdTable == NULL ) {
+            psError( __func__, "Null metadata table not allowed" );
+            return false;
+        }
+        
+    // Select removal by key or index
+    if ( key != NULL ) {
+    
             // Remove by key name
-            entry = (psMetadataItem*)psHashLookup(mdTable, key);
-            if(entry == NULL) {
-                psError(__func__, "Couldn't find metadata item remove. Name: %s", key);
-                return false;
-            }
-     
+            entry = ( psMetadataItem* ) psHashLookup( mdTable, key );
+            if ( entry == NULL ) {
+                    psError( __func__, "Couldn't find metadata item remove. Name: %s", key );
+                    return false;
+                }
+                
             numChildren = entry->items->size;
-            if(entry->type==PS_META_ITEM_SET && numChildren>0){
-     
-                // Table entry has children. Entry and children must be removed from metadata collection's list
-                psListSetIterator(list, PS_LIST_HEAD);
-                entryChild = psListGetCurrent(list);
-                while (entryChild != NULL) {
-                    if(!psListRemove(mdList, entry, PS_LIST_UNKNOWN)) {
-                        psError(__func__, "Couldn't remove metadata item from list. Name: %s", key);
-                        return false;
-                    }
-                }
-                entryChild = psListGetNext(list);
-            } else {
-     
-                // Table entry does not have children. Entry only must be removed from metadata collection's list
-                if(!psListRemove(mdList, entry, PS_LIST_UNKNOWN)) {
-                    psError(__func__, "Couldn't remove metadata item from list. Name: %s", key);
+            if ( entry->type == PS_META_ITEM_SET && numChildren > 0 ) {
+            
+                    // Table entry has children. Entry and children must be removed from metadata collection's list
+                    psListSetIterator( mdList, PS_LIST_HEAD );
+                    entryChild = psListGetCurrent( mdList );
+                    while ( entryChild != NULL ) {
+                            if ( !psListRemove( entry->items, entryChild, PS_LIST_UNKNOWN ) ) {
+                                    psError( __func__, "Couldn't remove metadata item from list. Name: %s", key );
+                                    return false;
+                                }
+                            entryChild = psListGetNext( entry->items );
+                        }
+                }
+                
+            // Remove entry from metadata collection's list
+            if ( !psListRemove( mdList, entry, PS_LIST_UNKNOWN ) ) {
+                    psError( __func__, "Couldn't remove metadata item from list. Name: %s", key );
                     return false;
                 }
-     
-            }
-     
-            // Remove entry from table once duplictes have been removed from the metadata collection's list
-            if(!psHashRemove(mdHash, key)) {
-                psError(__func__, "Couldn't remove metadata item from table. Name: %s", key);
-                return false;
-            }
+                
+            // Remove entry from metadata collection's table
+            if ( !psHashRemove( mdTable, key ) ) {
+                    psError( __func__, "Couldn't remove metadata item from table. Name: %s", key );
+                    return false;
+                }
         } else {
+        
             // Remove by index
-     
-        }*/
-
+            entry = psListGet( mdList, where );
+            if ( entry == NULL ) {
+                    psError( __func__, "Couldn't find metadata item from list. Index: %d", where );
+                    return false;
+                }
+                
+            key = entry->name;
+            if ( key == NULL ) {
+                    psError( __func__, "Null key name not allowed. Index: %d", where );
+                    return false;
+                }
+                
+            // Use recursive remove, now that key is known
+            psMetadataRemove( md, PS_LIST_UNKNOWN, key );
+        }
+        
     return true;
 }
 
+psMetadataItem *psMetadataLookup( psMetadata *restrict md, const char *restrict key )
+{
+    psHash * mdTable = NULL;
+    psMetadataItem *entry = NULL;
+    
+    mdTable = md->table;
+    if ( mdTable == NULL ) {
+            psError( __func__, "Null metadata table not allowed" );
+            return NULL;
+        }
+        
+    if ( key == NULL ) {
+            psError( __func__, "Null key name not allowed" );
+            return NULL;
+        }
+        
+    entry = ( psMetadataItem* ) psHashLookup( mdTable, key );
+    if ( entry == NULL ) {
+            psError( __func__, "Could not find metadata item with given key. Key: %s", key );
+            return NULL;
+        }
+        
+    return entry;
+}
+
+psMetadataItem *psMetadataGet( psMetadata *restrict md, int where )
+{
+    psList * mdList = NULL;
+    psMetadataItem *entry = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    entry = ( psMetadataItem* ) psListGet( mdList, where );
+    if ( entry == NULL ) {
+            psError( __func__, "Couldn't find metadata item with given index. Index: %d", where );
+            return NULL;
+        }
+        
+    return entry;
+}
+
+bool psMetadataSetIterator( psMetadata *restrict md, int where )
+{
+    psList * mdList = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return false;
+        }
+        
+    psListSetIterator( mdList, where );
+    
+    return true;
+}
+
+psMetadataItem *psMetadataGetNext( psMetadata *restrict md, const char *restrict match, int which )
+{
+    psList * mdList = NULL;
+    psMetadataItem *entry = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    psListSetIterator( mdList, which );
+    entry = psListGetCurrent( mdList );
+    while ( entry != NULL ) {
+            if ( !strncmp( match, entry->name, strlen( match ) ) ) {
+            
+                    // Match found
+                    return entry;
+                }
+            entry = psListGetNext( mdList );
+        }
+        
+    // Match not found
+    if ( entry == NULL ) {
+            psError( __func__, "Couldn't find metadata item with given match. Match: %s", match );
+        }
+        
+    return entry;
+}
+
+psMetadataItem *psMetadataGetPrevious( psMetadata *restrict md, const char *restrict match, int which )
+{
+    psList * mdList = NULL;
+    psMetadataItem *entry = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    psListSetIterator( mdList, which );
+    entry = psListGetCurrent( mdList );
+    while ( entry != NULL ) {
+            if ( !strncmp( match, entry->name, strlen( match ) ) ) {
+            
+                    // Match found
+                    return entry;
+                }
+            entry = psListGetPrevious( mdList );
+        }
+        
+    // Match not found
+    if ( entry == NULL ) {
+            psError( __func__, "Couldn't find metadata item with given match. Match: %s", match );
+        }
+        
+    return entry;
+}
+
+void psMetadataItemPrint( FILE *fd, const char *format, const psMetadataItem *restrict metadataItem )
+{
+    psMetadataType type;
+    
+    if ( fd == NULL ) {
+            psError( __func__, "Null file descriptor not allowed" );
+            return ;
+        }
+        
+    if ( format == NULL ) {
+            psError( __func__, "Null format not allowed" );
+            return ;
+        }
+        
+    if ( metadataItem == NULL ) {
+            psError( __func__, "Null metadata not allowed" );
+            return ;
+        }
+        
+    type = metadataItem->type;
+    
+    switch ( type ) {
+            case PS_META_S32:
+            fprintf( fd, format, metadataItem->data.S32 );
+            break;
+            case PS_META_F32:
+            fprintf( fd, format, metadataItem->data.F32 );
+            break;
+            case PS_META_F64:
+            fprintf( fd, format, metadataItem->data.F64 );
+            break;
+            case PS_META_STR:
+            fprintf( fd, format, metadataItem->data.V );
+            break;
+            case PS_META_ITEM_SET:
+            case PS_META_IMG:
+            case PS_META_JPEG:
+            case PS_META_PNG:
+            case PS_META_ASTROM:
+            case PS_META_UNKNOWN:
+            default:
+            psError( __func__, " Invalid psMetadataType to print: %d", type );
+        }
+}
+
+psMetadata *psMetadataReadHeader( psMetadata *output, const char *extname, int extnum, const char *filename )
+{
+    return NULL;
+    
+}
+
+psMetadata *psMetadataFReadHeader( psMetadata *output, const char *extname, int extnum, fitsfile *fd )
+{
+    bool success;
+    char keyType;
+    char keyName[ MAX_VAL_SIZE ];
+    char keyValue[ MAX_VAL_SIZE ];
+    char keyComment[ MAX_VAL_SIZE ];
+    char fitsErr[ MAX_ERR_MESSAGE_LENGTH ];
+    char* tempExtname = NULL;
+    int i;
+    int hduType = 0;
+    int status = 0;
+    int numKeys = 0;
+    psMetadataType metadataItemType;
+    
+    if ( fd == NULL ) {
+            psError( __func__, "Null FITS file descriptor not allowed" );
+            return NULL;
+        }
+        
+    if ( extname == NULL && extnum == 0 ) {
+            psError( __func__, "Null extname AND extnum = 0 not allowed" );
+            return NULL;
+        } else if ( extname && extnum ) {
+            psError( __func__, "Both extname AND extnum arguments should not have valid values." );
+            return NULL;
+        }
+        
+    // Allocate metadata if user didn't
+    if ( output == NULL ) {
+            output = psMetadataAlloc();
+            return NULL;
+        }
+        
+    // Move to user designated HDU number or HDU name in FITS file. HDU numbers starts at one.
+    if ( extname == NULL ) {
+            if ( fits_movabs_hdu( fd, extnum, &hduType, &status ) != 0 ) {
+                    fits_get_errstatus( status, fitsErr );
+                    psError( __func__, "FITS error while locating header: %s", fitsErr );
+                    status = 0;
+                    fits_close_file( fd, &status );
+                    return NULL;
+                }
+        } else if ( extnum > 0 ) {
+            tempExtname = ( char* ) psAlloc( strlen( extname ) + 1 ); // fits_movnam_hdu doesn't like const part of extname
+            strncpy( tempExtname, extname, MAX_VAL_SIZE );
+            if ( fits_movnam_hdu( fd, ANY_HDU, tempExtname, 0, &status ) != 0 ) {
+                    fits_get_errstatus( status, fitsErr );
+                    psError( __func__, "FITS error while locating header: %s", fitsErr );
+                    status = 0;
+                    fits_close_file( fd, &status );
+                    psFree( tempExtname );
+                    return NULL;
+                }
+            psFree( tempExtname );
+        }
+        
+    // Get number of key names
+    if ( fits_get_hdrpos( fd, &numKeys, NULL, &status ) != 0 ) {
+            fits_get_errstatus( status, fitsErr );
+            psError( __func__, "FITS error while reading keys: %s", fitsErr );
+            status = 0;
+            fits_close_file( fd, &status );
+            return NULL;
+        }
+        
+    // Get each key name. Keywords start at one.
+    for ( i = 1; i <= numKeys; i++ ) {
+            if ( fits_read_keyn( fd, i, keyName, keyValue, keyComment, &status ) != 0 ) {
+                    fits_get_errstatus( status, fitsErr );
+                    psError( __func__, "FITS error while reading key number %d: %s", i, fitsErr );
+                    status = 0;
+                    fits_close_file( fd, &status );
+                    return NULL;
+                }
+                
+            if ( fits_get_keytype( keyValue, &keyType, &status ) != 0 ) {
+                    fits_get_errstatus( status, fitsErr );
+                    psError( __func__, "FITS error while determining key type: %s", fitsErr );
+                    status = 0;
+                    fits_close_file( fd, &status );
+                    return NULL;
+                }
+                
+            switch ( keyType ) {
+                    case 'I':
+                    metadataItemType = PS_META_S32;
+                    success = psMetadataAdd( output, PS_LIST_HEAD, keyName, metadataItemType, keyComment, atoi( keyValue ) );
+                    break;
+                    case 'F':
+                    metadataItemType = PS_META_F64;
+                    success = psMetadataAdd( output, PS_LIST_HEAD, keyName, metadataItemType, keyComment, atof( keyValue ) );
+                    break;
+                    case 'C':
+                    metadataItemType = PS_META_STR;
+                    success = psMetadataAdd( output, PS_LIST_HEAD, keyName, metadataItemType, keyComment, keyValue );
+                    break;
+                    case 'L':
+                    case 'X':
+                    default:
+                    psError( __func__, "Invalid psMetadataType: %c", keyType );
+                    return NULL;
+                }
+                
+            if ( !success ) {
+                    psError( __func__, "Failed to add metadata item. Name: %s", keyName );
+                }
+        }
+        
+    return output;
+}
Index: /trunk/psLib/src/collections/psMetadata.h
===================================================================
--- /trunk/psLib/src/collections/psMetadata.h	(revision 1350)
+++ /trunk/psLib/src/collections/psMetadata.h	(revision 1351)
@@ -1,18 +1,18 @@
 /** @file  psMetadata.h
- *
- *  @brief Contains metadata struuctures, enumerations and functions prototypes
- *
- *  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
- *  prototypes necessary creating psLib metadata APIs
- *
- *  @ingroup Metadata
- *
- *  @author Ross Harman, MHPCC
- *
- *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-07-29 20:16:34 $
- *
- *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
- */
+*
+*  @brief Contains metadata struuctures, enumerations and functions prototypes
+*
+*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+*  prototypes necessary creating psLib metadata APIs
+*
+*  @ingroup Metadata
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-07-30 19:37:07 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
 #ifndef PS_METADATA_H
 #define PS_METADATA_H
@@ -30,14 +30,14 @@
  */
 typedef enum {
-    PS_META_ITEM_SET = 0,               ///< Null. Metadata is in psMetadataItem.items
-    PS_META_S32,                        ///< Signed 32-bit integer data.
-    PS_META_F32,                        ///< Single-precision float data.
-    PS_META_F64,                        ///< Double-precision float data.
-    PS_META_STR,                        ///< String data (Stored in as void *).
-    PS_META_IMG,                        ///< Image data (Stored in as void *).
-    PS_META_JPEG,                       ///< JPEG data (Stored in as void .
-    PS_META_PNG,                        ///< PNG data (Stored in as void *).
-    PS_META_ASTROM,                     ///< Astrometric coefficients (Stored in as void *).
-    PS_META_UNKNOWN,                    ///< Other data (Stored in as void *).
+    PS_META_ITEM_SET = 0,                ///< Null. Metadata is in psMetadataItem.items
+    PS_META_S32,                         ///< Signed 32-bit integer data.
+    PS_META_F32,                         ///< Single-precision float data.
+    PS_META_F64,                         ///< Double-precision float data.
+    PS_META_STR,                         ///< String data (Stored in as void *).
+    PS_META_IMG,                         ///< Image data (Stored in as void *).
+    PS_META_JPEG,                        ///< JPEG data (Stored in as void .
+    PS_META_PNG,                         ///< PNG data (Stored in as void *).
+    PS_META_ASTROM,                      ///< Astrometric coefficients (Stored in as void *).
+    PS_META_UNKNOWN,                     ///< Other data (Stored in as void *).
     PS_META_NTYPE                       ///< Number of types. Must be last.
 } psMetadataType;
@@ -49,18 +49,18 @@
  */
 typedef struct psMetadataItem
-{
-    const int id;                       ///< Unique ID for metadata item.
-    char *restrict name;                ///< Name of metadata item.
-    psMetadataType type;                ///< Type of metadata item.
-    union
     {
-        psS32   S32;                    ///< Signed 32-bit integer data.
-        psF32   F32;                    ///< Single-precision float data.
-        psF64   F64;                    ///< Double-precision float data.
-        psPTR     V;                    ///< Pointer to other type of data.
-    }data;                              ///< Union for data types.
-    char *comment;                      ///< Optional comment ("", not NULL).
-    psList *restrict items;             ///< List of psMetadataItems with same name.
-}
+        const int id;                       ///< Unique ID for metadata item.
+        char *restrict name;                ///< Name of metadata item.
+        psMetadataType type;                ///< Type of metadata item.
+        union
+            {
+                psS32 S32;                    ///< Signed 32-bit integer data.
+                psF32 F32;                    ///< Single-precision float data.
+                psF64 F64;                    ///< Double-precision float data.
+                psPTR V;                    ///< Pointer to other type of data.
+            }data;                              ///< Union for data types.
+        char *comment;                      ///< Optional comment ("", not NULL).
+        psList *restrict items;             ///< List of psMetadataItems with same name.
+    }
 psMetadataItem;
 
@@ -72,8 +72,8 @@
  */
 typedef struct psMetadata
-{
-    psList *restrict list;
-    psHash *restrict table;
-}
+    {
+        psList *restrict list;
+        psHash *restrict table;
+    }
 psMetadata;
 
@@ -97,7 +97,7 @@
  */
 psMetadataItem *psMetadataItemAlloc(
-    const char *name,                   ///< Name of metadata item.
-    psMetadataType type,                ///< Type of metadata item.
-    const char *comment,                ///< Comment for metadata item.
+    const char *name,                    ///< Name of metadata item.
+    psMetadataType type,                 ///< Type of metadata item.
+    const char *comment,                 ///< Comment for metadata item.
     ...                                 ///< Arguments for name formatting and metadata item data.
 );
@@ -117,7 +117,7 @@
  */
 psMetadataItem *psMetadataItemAllocV(
-    const char *name,                   ///< Name of metadata item.
-    psMetadataType type,                ///< Type of metadata item.
-    const char *comment,                ///< Comment for metadata item.
+    const char *name,                    ///< Name of metadata item.
+    psMetadataType type,                 ///< Type of metadata item.
+    const char *comment,                 ///< Comment for metadata item.
     va_list list                        ///< Arguments for name formatting and metadata item data.
 );
@@ -140,6 +140,6 @@
  */
 bool psMetadataAddItem(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
-    int where,                          ///< Location to be added.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
+    int where,                           ///< Location to be added.
     psMetadataItem *restrict item       ///< Metadata item to be added.
 );
@@ -152,9 +152,9 @@
  */
 bool psMetadataAdd(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
-    int where,                          ///< Location to be added.
-    const char *name,                   ///< Name of metadata item.
-    psMetadataType type,                ///< Type of metadata item.
-    const char *comment,                ///< Comment for metadata item.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
+    int where,                           ///< Location to be added.
+    const char *name,                    ///< Name of metadata item.
+    psMetadataType type,                 ///< Type of metadata item.
+    const char *comment,                 ///< Comment for metadata item.
     ...                                 ///< Arguments for name formatting and metadata item data.
 );
@@ -170,6 +170,6 @@
  */
 bool psMetadataRemove(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
-    int where,                          ///< Location to be removed.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
+    int where,                           ///< Location to be removed.
     const char *restrict key            ///< Name of metadata key.
 );
@@ -183,5 +183,5 @@
  */
 psMetadataItem *psMetadataLookup(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
     const char *restrict key            ///< Name of metadata key.
 );
@@ -194,5 +194,5 @@
  */
 psMetadataItem *psMetadataGet(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
     int where                           ///< Location to be retrieved.
 );
@@ -205,5 +205,5 @@
  */
 bool psMetadataSetIterator(
-    psMetadata *restrict md,            ///< Metadata collection to iterate.
+    psMetadata *restrict md,             ///< Metadata collection to iterate.
     int where                           ///< Location of iterator.
 );
@@ -216,6 +216,6 @@
  */
 psMetadataItem *psMetadataGetNext(
-    psMetadata *restrict md,            ///< Metadata collection to iterate.
-    const char *restrict match,         ///< Beginning of key name.
+    psMetadata *restrict md,             ///< Metadata collection to iterate.
+    const char *restrict match,          ///< Beginning of key name.
     int which                           ///< Iterator to be used.
 );
@@ -228,6 +228,6 @@
  */
 psMetadataItem *psMetadataGetPrevious(
-    psMetadata *restrict md,            ///< Metadata collection to iterate.
-    const char *restrict match,         ///< Beginning of key name.
+    psMetadata *restrict md,             ///< Metadata collection to iterate.
+    const char *restrict match,          ///< Beginning of key name.
     int which                           ///< Iterator to be used.
 );
@@ -244,7 +244,7 @@
  */
 void psMetadataItemPrint(
-    FILE *fd,                           ///< Pointer to file to write metadata item.
-    const char *format,                 ///< Format to print metadata item.
-    const psMetadataItem *restrict md   ///< Metadata item to print.
+    FILE *fd,                                    ///< Pointer to file to write metadata item.
+    const char *format,                          ///< Format to print metadata item.
+    const psMetadataItem *restrict metadataItem ///< Metadata item to print.
 );
 
@@ -256,7 +256,7 @@
  */
 psMetadata *psMetadataReadHeader(
-    psMetadata *output,                 ///< Resulting metadata from read.
-    const char *extname,                ///< File name extension string.
-    int extnum,                         ///< File name extension number.
+    psMetadata *output,                  ///< Resulting metadata from read.
+    const char *extname,                 ///< File name extension string.
+    int extnum,                          ///< File name extension number.
     const char *filename                ///< Name of file to read.
 );
@@ -269,8 +269,8 @@
  */
 psMetadata *psMetadataFReadHeader(
-    psMetadata *output,                 ///< Resulting metadata from read.
-    const char *extname,                ///< File name extension string.
-    int extnum,                         ///< File name extension number.
-    FILE *fd                            ///< Pointer to file to read.
+    psMetadata *output,                  ///< Resulting metadata from read.
+    const char *extname,                 ///< File name extension string.
+    int extnum,                          ///< File name extension number.
+    fitsfile *fd                        ///< Pointer to file to read.
 );
 /// @}
Index: /trunk/psLib/src/types/psMetadata.c
===================================================================
--- /trunk/psLib/src/types/psMetadata.c	(revision 1350)
+++ /trunk/psLib/src/types/psMetadata.c	(revision 1351)
@@ -1,19 +1,19 @@
 /** @file  psMetadata.c
- *
- *
- *  @brief Contains metadata struuctures, enumerations and functions prototypes
- *
- *  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
- *  prototypes necessary creating psLib metadata APIs
- *
- *  @ingroup Metadata
- *
- *  @author Ross Harman, MHPCC
- *
- *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-07-29 02:04:20 $
- *
- *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
- */
+*
+*
+*  @brief Contains metadata struuctures, enumerations and functions prototypes
+*
+*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+*  prototypes necessary creating psLib metadata APIs
+*
+*  @ingroup Metadata
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-07-30 19:36:52 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
 
 /******************************************************************************/
@@ -24,4 +24,5 @@
 #include<string.h>
 
+#include "fitsio.h"
 #include "psType.h"
 #include "psMemory.h"
@@ -37,5 +38,9 @@
 /******************************************************************************/
 
-// None
+// Maximum metadata length string
+#define MAX_VAL_SIZE 1024
+
+// Maximum metadata error length
+#define MAX_ERR_MESSAGE_LENGTH 1024
 
 /******************************************************************************/
@@ -60,33 +65,33 @@
 /*  FUNCTION IMPLEMENTATION - LOCAL                                          */
 /*****************************************************************************/
-static void metadataItemFree(psMetadataItem *metadataItem)
+static void metadataItemFree( psMetadataItem *metadataItem )
 {
     psMetadataType type;
-
+    
     type = metadataItem->type;
-
-    if (metadataItem == NULL) {
-        return;
-    }
-
-    psFree(metadataItem->name);
-    psFree(metadataItem->comment);
-
-    if(type==PS_META_STR || type==PS_META_IMG || type==PS_META_JPEG || type==PS_META_PNG ||
-            type==PS_META_ASTROM || type==PS_META_UNKNOWN) {
-        psFree(metadataItem->data.V);
-    }
-
-    psFree(metadataItem->items);
-}
-
-static void metadataFree(psMetadata *metadata)
-{
-    if (metadata == NULL) {
-        return;
-    }
-
-    psFree(metadata->list);
-    psFree(metadata->table);
+    
+    if ( metadataItem == NULL ) {
+            return ;
+        }
+        
+    psFree( metadataItem->name );
+    psFree( metadataItem->comment );
+    
+    if ( type == PS_META_STR || type == PS_META_IMG || type == PS_META_JPEG || type == PS_META_PNG ||
+            type == PS_META_ASTROM || type == PS_META_UNKNOWN ) {
+            psFree( metadataItem->data.V );
+        }
+        
+    psFree( metadataItem->items );
+}
+
+static void metadataFree( psMetadata *metadata )
+{
+    if ( metadata == NULL ) {
+            return ;
+        }
+        
+    psFree( metadata->list );
+    psFree( metadata->table );
 }
 
@@ -95,279 +100,582 @@
 /*****************************************************************************/
 
-psMetadataItem *psMetadataItemAlloc(const char *name, psMetadataType type, const char *comment, ...)
+psMetadataItem *psMetadataItemAlloc( const char *name, psMetadataType type, const char *comment, ... )
 {
     va_list argPtr;
     psMetadataItem *metadataItem = NULL;
-
+    
     // Get the variable list parameters to pass to allocation function
-    va_start(argPtr, comment);
-
+    va_start( argPtr, comment );
+    
     // Call metadata item allocation
-    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
-
+    metadataItem = psMetadataItemAllocV( name, type, comment, argPtr );
+    
     // Clean up stack after variable arguement has been used
-    va_end(argPtr);
-
+    va_end( argPtr );
+    
     return metadataItem;
 }
 
-psMetadataItem *psMetadataItemAllocV(const char *name, psMetadataType type, const char *comment, va_list argPtr)
-{
-    psMetadataItem *metadataItem = NULL;
-
-    if(name == NULL) {
-        psError(__func__, "Null value for string not allowed");
-        return NULL;
-    }
-
+psMetadataItem *psMetadataItemAllocV( const char *name, psMetadataType type, const char *comment, va_list argPtr )
+{
+    psMetadataItem * metadataItem = NULL;
+    
+    if ( name == NULL ) {
+            psError( __func__, "Null value for string not allowed" );
+            return NULL;
+        }
+        
     // Allocate metadata item
-    metadataItem = (psMetadataItem *)psAlloc(sizeof(psMetadataItem));
-    if(metadataItem == NULL) {
-        psAbort(__func__,"Failed to allocate memory");
-    }
-
+    metadataItem = ( psMetadataItem * ) psAlloc( sizeof( psMetadataItem ) );
+    if ( metadataItem == NULL ) {
+            psAbort( __func__, "Failed to allocate memory" );
+        }
+        
     // Set deallocator
-    p_psMemSetDeallocator(metadataItem,(psFreeFcn)metadataItemFree);
-
+    p_psMemSetDeallocator( metadataItem, ( psFreeFcn ) metadataItemFree );
+    
     // Allocate and set metadata item comment
-    metadataItem->comment = (char *)psAlloc(sizeof(char)*MAX_STRING_LENGTH);
-    if(comment == NULL) {
-        // Per SDRS, null isn't allowed, must use "" instead
-        strncpy(metadataItem->comment, "", MAX_STRING_LENGTH);
-    } else {
-        strncpy(metadataItem->comment, comment, MAX_STRING_LENGTH);
-    }
-
-    // Set metadata item id
-    *(int*)(&metadataItem->id) = ++metadataId;
-
+    metadataItem->comment = ( char * ) psAlloc( sizeof( char ) * MAX_STRING_LENGTH );
+    if ( comment == NULL ) {
+            // Per SDRS, null isn't allowed, must use "" instead
+            strncpy( metadataItem->comment, "", MAX_STRING_LENGTH );
+        } else {
+            strncpy( metadataItem->comment, comment, MAX_STRING_LENGTH );
+        }
+        
+    // Set metadata item unique id
+    *( int* ) ( &metadataItem->id ) = ++metadataId;
+    
     // Set metadata item type
     metadataItem->type = type;
-
+    
     // Set metadata item value
-    switch(type) {
-    case PS_META_S32:
-        metadataItem->data.S32 = va_arg(argPtr, psS32);
-        break;
-    case PS_META_F32:
-        metadataItem->data.F32 = (psF32)va_arg(argPtr, psF64);
-        break;
-    case PS_META_F64:
-        metadataItem->data.F64 = va_arg(argPtr, psF64);
-        break;
-    case PS_META_STR:
-    case PS_META_IMG:
-    case PS_META_JPEG:
-    case PS_META_PNG:
-    case PS_META_ASTROM:
-    case PS_META_UNKNOWN:
-        metadataItem->data.V = psMemIncrRefCounter(va_arg(argPtr, psPTR));
-        break;
-    default:
-        psError(__func__, " Invalid psMetadataType: %d", type);
-    }
-
+    switch ( type ) {
+            case PS_META_S32:
+            metadataItem->data.S32 = va_arg( argPtr, psS32 );
+            break;
+            case PS_META_F32:
+            metadataItem->data.F32 = ( psF32 ) va_arg( argPtr, psF64 );
+            break;
+            case PS_META_F64:
+            metadataItem->data.F64 = va_arg( argPtr, psF64 );
+            break;
+            case PS_META_STR:
+            case PS_META_IMG:
+            case PS_META_JPEG:
+            case PS_META_PNG:
+            case PS_META_ASTROM:
+            case PS_META_UNKNOWN:
+            metadataItem->data.V = psMemIncrRefCounter( va_arg( argPtr, psPTR ) );
+            break;
+            default:
+            psError( __func__, " Invalid psMetadataType: %d", type );
+        }
+        
     // Allocate and set metadata item name
-    metadataItem->name = (char *)psAlloc(sizeof(char)*MAX_STRING_LENGTH);
-    vsprintf(metadataItem->name, name, argPtr);
-
+    metadataItem->name = ( char * ) psAlloc( sizeof( char ) * MAX_STRING_LENGTH );
+    vsprintf( metadataItem->name, name, argPtr );
+    
     // Allocate metadata items with same name.
-    metadataItem->items = psListAlloc(NULL);
-
+    metadataItem->items = psListAlloc( NULL );
+    
     return metadataItem;
 }
 
-psMetadata *psMetadataAlloc(void)
-{
-    psList *list = NULL;
+psMetadata *psMetadataAlloc( void )
+{
+    psList * list = NULL;
     psHash *table = NULL;
     psMetadata *metadata = NULL;
-
+    
     // Allocate metadata
-    metadata = (psMetadata *)psAlloc(sizeof(psMetadata));
-    if(metadata == NULL) {
-        psAbort(__func__,"Failed to allocate metadata");
-    }
-
+    metadata = ( psMetadata * ) psAlloc( sizeof( psMetadata ) );
+    if ( metadata == NULL ) {
+            psAbort( __func__, "Failed to allocate metadata" );
+        }
+        
     // Set deallocator
-    p_psMemSetDeallocator(metadata,(psFreeFcn)metadataFree);
-
+    p_psMemSetDeallocator( metadata, ( psFreeFcn ) metadataFree );
+    
     // Allocate internal containers
-    list = (psList *)psAlloc(sizeof(psList));
-    if(list == NULL) {
-        psAbort(__func__,"Failed to allocate list");
-    }
-
-    table = (psHash *)psAlloc(sizeof(psHash));
-    if(table == NULL) {
-        psAbort(__func__,"Failed to allocate table");
-    }
-
+    list = ( psList * ) psAlloc( sizeof( psList ) );
+    if ( list == NULL ) {
+            psAbort( __func__, "Failed to allocate list" );
+        }
+        
+    table = ( psHash * ) psAlloc( sizeof( psHash ) );
+    if ( table == NULL ) {
+            psAbort( __func__, "Failed to allocate table" );
+        }
+        
     return metadata;
 }
 
-bool psMetadataAddItem(psMetadata *restrict md, int where, psMetadataItem *restrict metadataItem)
-{
-    char *key = NULL;
+bool psMetadataAddItem( psMetadata *restrict md, int where, psMetadataItem *restrict metadataItem )
+{
+    char * key = NULL;
     psHash *mdTable = NULL;
     psList *mdList = NULL;
     psMetadataItem *value = NULL;
     psMetadataType type = PS_META_ITEM_SET;
-
-    if(md == NULL) {
-        psError(__func__, "Null metadata collection not allowed");
-        return false;
-    }
-
-    if(metadataItem == NULL) {
-        psError(__func__, "Null metadata item not allowed");
-        return false;
-    }
-
+    
+    if ( md == NULL ) {
+            psError( __func__, "Null metadata collection not allowed" );
+            return false;
+        }
+        
+    if ( metadataItem == NULL ) {
+            psError( __func__, "Null metadata item not allowed" );
+            return false;
+        }
+        
     type = metadataItem->type;
-
+    
     mdTable = md->table;
-    if(mdTable == NULL) {
-        psError(__func__, "Null metadata table not allowed");
-        return false;
-    }
-
-    mdList = md->list;
-    if(mdList == NULL) {
-        psError(__func__, "Null metadata list not allowed");
-        return false;
-    }
-
+    if ( mdTable == NULL ) {
+            psError( __func__, "Null metadata table not allowed" );
+            return false;
+        }
+        
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return false;
+        }
+        
     key = metadataItem->name;
-    if(key == NULL) {
-        psError(__func__, "Null key item not allowed");
-        return false;
-    }
-
+    if ( key == NULL ) {
+            psError( __func__, "Null key item not allowed" );
+            return false;
+        }
+        
     // Check if key is already in table
-    value = (psMetadataItem*)psHashLookup(mdTable, key);
-    if(value!=NULL && type!=PS_META_ITEM_SET) {
-
-        // The key was found and the new metadata item is a leaf node (its type isn't PS_META_ITEM_SET), so
-        // add the new metadata item to hash as a child of the existing metadata item folder node.
-        if(!psListAdd(value->items, metadataItem, where)) {
-            psError(__func__, "Couldn't add metadata item to items list. Name: %s",
-                    metadataItem->name);
-            return false;
-        }
-    } else if(value != NULL) {
-
-        // The key was found and the new metadata item is a folder node. Don't add new metadata item, since
-        // it will wipe out existing node.
-        psError(__func__, "Metadata already exists in metadata collection. Item not added. Name: %s",
-                metadataItem->name);
-        return false;
-    } else {
-
-        // Duplicate key not found. Add new metadata item to metadata collection's hash
-        if(!psHashAdd(mdTable, key, metadataItem)) {
-            psError(__func__, "Couldn't add metadata item to metadata collection table. Name: %s",
-                    metadataItem->name);
-            return false;
-        }
-    }
-
+    value = ( psMetadataItem* ) psHashLookup( mdTable, key );
+    if ( value != NULL && type != PS_META_ITEM_SET ) {
+    
+            // The key was found and the new metadata item is a leaf node (its type isn't PS_META_ITEM_SET), so
+            // add the new metadata item to hash as a child of the existing metadata item folder node.
+            if ( !psListAdd( value->items, metadataItem, where ) ) {
+                    psError( __func__, "Couldn't add metadata item to items list. Name: %s",
+                             metadataItem->name );
+                    return false;
+                }
+        } else if ( value != NULL ) {
+        
+            // The key was found and the new metadata item is a folder node. Don't add new metadata item, since
+            // it will wipe out existing node.
+            psError( __func__, "Metadata already exists in metadata collection. Item not added. Name: %s",
+                     metadataItem->name );
+            return false;
+        } else {
+        
+            // Duplicate key not found. Add new metadata item to metadata collection's hash
+            if ( !psHashAdd( mdTable, key, metadataItem ) ) {
+                    psError( __func__, "Couldn't add metadata item to metadata collection table. Name: %s",
+                             metadataItem->name );
+                    return false;
+                }
+        }
+        
     // Add all items to metadata collection's list, even if they have the same metadata item names
-    if(!psListAdd(md->list, metadataItem, where)) {
-        psError(__func__, "Couldn't add metadata item to metadata collection list. Name: %s",
-                metadataItem->name);
-        return false;
-    }
-
+    if ( !psListAdd( md->list, metadataItem, where ) ) {
+            psError( __func__, "Couldn't add metadata item to metadata collection list. Name: %s",
+                     metadataItem->name );
+            return false;
+        }
+        
     return true;
 }
 
-bool psMetadataAdd(psMetadata *restrict md, int where, const char *name, psMetadataType type,
-                   const char *comment, ...)
+bool psMetadataAdd( psMetadata *restrict md, int where, const char *name, psMetadataType type,
+                    const char *comment, ... )
 {
     va_list argPtr;
     psMetadataItem *metadataItem = NULL;
-
-    va_start(argPtr, comment);
-    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
-    va_end(argPtr);
-
-    return psMetadataAddItem(md, where, metadataItem);
-}
-
-/** Remove an item from metadata collection.
- *
- * Items may be removed from metadata by specifing a key or location. If the key is null, the where argument
- * is used instead. If name is not null, where is set to PS_LIST_UNKNOWN. If the item is found, it is removed
- * from the metadata and true is returned.  If the key is not unique, then all items corresponding to it are
- * removed.
- *
- * @return bool: True for success, false for failure.
- */
-bool psMetadataRemove(psMetadata *restrict md, int where, const char *restrict key)
-{
-    /*    int i = 0;
-        int numChildren = 0;
-        psList mdList = NULL;
-        psHash mdHash = NULL;
-        psMetadataItem *entry = NULL;
-        psMetadataItem *entryChild = NULL;
-     
-        mdList = md->list
-        if(mdList == NULL) {
-            psError(__func__, "Null metadata list not allowed");
-            return false;
-        }
-     
-        mdTable = md->table;
-        if(mdTable == NULL) {
-            psError(__func__, "Null metadata table not allowed");
-            return false;
-        }
-     
-        // Select removal by key or index
-        if(key != NULL){
-     
+    
+    va_start( argPtr, comment );
+    metadataItem = psMetadataItemAllocV( name, type, comment, argPtr );
+    va_end( argPtr );
+    
+    if ( !psMetadataAddItem( md, where, metadataItem ) ) {
+            psError( __func__, "Couldn't add metadata item to metadata collection list. Name: %s",
+                     metadataItem->name );
+            psFree( metadataItem );
+            return false;
+        }
+        
+    return true;
+}
+
+bool psMetadataRemove( psMetadata *restrict md, int where, const char *restrict key )
+{
+    int numChildren = 0;
+    psList *mdList = NULL;
+    psHash *mdTable = NULL;
+    psMetadataItem *entry = NULL;
+    psMetadataItem *entryChild = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return false;
+        }
+        
+    mdTable = md->table;
+    if ( mdTable == NULL ) {
+            psError( __func__, "Null metadata table not allowed" );
+            return false;
+        }
+        
+    // Select removal by key or index
+    if ( key != NULL ) {
+    
             // Remove by key name
-            entry = (psMetadataItem*)psHashLookup(mdTable, key);
-            if(entry == NULL) {
-                psError(__func__, "Couldn't find metadata item remove. Name: %s", key);
-                return false;
-            }
-     
+            entry = ( psMetadataItem* ) psHashLookup( mdTable, key );
+            if ( entry == NULL ) {
+                    psError( __func__, "Couldn't find metadata item remove. Name: %s", key );
+                    return false;
+                }
+                
             numChildren = entry->items->size;
-            if(entry->type==PS_META_ITEM_SET && numChildren>0){
-     
-                // Table entry has children. Entry and children must be removed from metadata collection's list
-                psListSetIterator(list, PS_LIST_HEAD);
-                entryChild = psListGetCurrent(list);
-                while (entryChild != NULL) {
-                    if(!psListRemove(mdList, entry, PS_LIST_UNKNOWN)) {
-                        psError(__func__, "Couldn't remove metadata item from list. Name: %s", key);
-                        return false;
-                    }
-                }
-                entryChild = psListGetNext(list);
-            } else {
-     
-                // Table entry does not have children. Entry only must be removed from metadata collection's list
-                if(!psListRemove(mdList, entry, PS_LIST_UNKNOWN)) {
-                    psError(__func__, "Couldn't remove metadata item from list. Name: %s", key);
+            if ( entry->type == PS_META_ITEM_SET && numChildren > 0 ) {
+            
+                    // Table entry has children. Entry and children must be removed from metadata collection's list
+                    psListSetIterator( mdList, PS_LIST_HEAD );
+                    entryChild = psListGetCurrent( mdList );
+                    while ( entryChild != NULL ) {
+                            if ( !psListRemove( entry->items, entryChild, PS_LIST_UNKNOWN ) ) {
+                                    psError( __func__, "Couldn't remove metadata item from list. Name: %s", key );
+                                    return false;
+                                }
+                            entryChild = psListGetNext( entry->items );
+                        }
+                }
+                
+            // Remove entry from metadata collection's list
+            if ( !psListRemove( mdList, entry, PS_LIST_UNKNOWN ) ) {
+                    psError( __func__, "Couldn't remove metadata item from list. Name: %s", key );
                     return false;
                 }
-     
-            }
-     
-            // Remove entry from table once duplictes have been removed from the metadata collection's list
-            if(!psHashRemove(mdHash, key)) {
-                psError(__func__, "Couldn't remove metadata item from table. Name: %s", key);
-                return false;
-            }
+                
+            // Remove entry from metadata collection's table
+            if ( !psHashRemove( mdTable, key ) ) {
+                    psError( __func__, "Couldn't remove metadata item from table. Name: %s", key );
+                    return false;
+                }
         } else {
+        
             // Remove by index
-     
-        }*/
-
+            entry = psListGet( mdList, where );
+            if ( entry == NULL ) {
+                    psError( __func__, "Couldn't find metadata item from list. Index: %d", where );
+                    return false;
+                }
+                
+            key = entry->name;
+            if ( key == NULL ) {
+                    psError( __func__, "Null key name not allowed. Index: %d", where );
+                    return false;
+                }
+                
+            // Use recursive remove, now that key is known
+            psMetadataRemove( md, PS_LIST_UNKNOWN, key );
+        }
+        
     return true;
 }
 
+psMetadataItem *psMetadataLookup( psMetadata *restrict md, const char *restrict key )
+{
+    psHash * mdTable = NULL;
+    psMetadataItem *entry = NULL;
+    
+    mdTable = md->table;
+    if ( mdTable == NULL ) {
+            psError( __func__, "Null metadata table not allowed" );
+            return NULL;
+        }
+        
+    if ( key == NULL ) {
+            psError( __func__, "Null key name not allowed" );
+            return NULL;
+        }
+        
+    entry = ( psMetadataItem* ) psHashLookup( mdTable, key );
+    if ( entry == NULL ) {
+            psError( __func__, "Could not find metadata item with given key. Key: %s", key );
+            return NULL;
+        }
+        
+    return entry;
+}
+
+psMetadataItem *psMetadataGet( psMetadata *restrict md, int where )
+{
+    psList * mdList = NULL;
+    psMetadataItem *entry = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    entry = ( psMetadataItem* ) psListGet( mdList, where );
+    if ( entry == NULL ) {
+            psError( __func__, "Couldn't find metadata item with given index. Index: %d", where );
+            return NULL;
+        }
+        
+    return entry;
+}
+
+bool psMetadataSetIterator( psMetadata *restrict md, int where )
+{
+    psList * mdList = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return false;
+        }
+        
+    psListSetIterator( mdList, where );
+    
+    return true;
+}
+
+psMetadataItem *psMetadataGetNext( psMetadata *restrict md, const char *restrict match, int which )
+{
+    psList * mdList = NULL;
+    psMetadataItem *entry = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    psListSetIterator( mdList, which );
+    entry = psListGetCurrent( mdList );
+    while ( entry != NULL ) {
+            if ( !strncmp( match, entry->name, strlen( match ) ) ) {
+            
+                    // Match found
+                    return entry;
+                }
+            entry = psListGetNext( mdList );
+        }
+        
+    // Match not found
+    if ( entry == NULL ) {
+            psError( __func__, "Couldn't find metadata item with given match. Match: %s", match );
+        }
+        
+    return entry;
+}
+
+psMetadataItem *psMetadataGetPrevious( psMetadata *restrict md, const char *restrict match, int which )
+{
+    psList * mdList = NULL;
+    psMetadataItem *entry = NULL;
+    
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    mdList = md->list;
+    if ( mdList == NULL ) {
+            psError( __func__, "Null metadata list not allowed" );
+            return NULL;
+        }
+        
+    psListSetIterator( mdList, which );
+    entry = psListGetCurrent( mdList );
+    while ( entry != NULL ) {
+            if ( !strncmp( match, entry->name, strlen( match ) ) ) {
+            
+                    // Match found
+                    return entry;
+                }
+            entry = psListGetPrevious( mdList );
+        }
+        
+    // Match not found
+    if ( entry == NULL ) {
+            psError( __func__, "Couldn't find metadata item with given match. Match: %s", match );
+        }
+        
+    return entry;
+}
+
+void psMetadataItemPrint( FILE *fd, const char *format, const psMetadataItem *restrict metadataItem )
+{
+    psMetadataType type;
+    
+    if ( fd == NULL ) {
+            psError( __func__, "Null file descriptor not allowed" );
+            return ;
+        }
+        
+    if ( format == NULL ) {
+            psError( __func__, "Null format not allowed" );
+            return ;
+        }
+        
+    if ( metadataItem == NULL ) {
+            psError( __func__, "Null metadata not allowed" );
+            return ;
+        }
+        
+    type = metadataItem->type;
+    
+    switch ( type ) {
+            case PS_META_S32:
+            fprintf( fd, format, metadataItem->data.S32 );
+            break;
+            case PS_META_F32:
+            fprintf( fd, format, metadataItem->data.F32 );
+            break;
+            case PS_META_F64:
+            fprintf( fd, format, metadataItem->data.F64 );
+            break;
+            case PS_META_STR:
+            fprintf( fd, format, metadataItem->data.V );
+            break;
+            case PS_META_ITEM_SET:
+            case PS_META_IMG:
+            case PS_META_JPEG:
+            case PS_META_PNG:
+            case PS_META_ASTROM:
+            case PS_META_UNKNOWN:
+            default:
+            psError( __func__, " Invalid psMetadataType to print: %d", type );
+        }
+}
+
+psMetadata *psMetadataReadHeader( psMetadata *output, const char *extname, int extnum, const char *filename )
+{
+    return NULL;
+    
+}
+
+psMetadata *psMetadataFReadHeader( psMetadata *output, const char *extname, int extnum, fitsfile *fd )
+{
+    bool success;
+    char keyType;
+    char keyName[ MAX_VAL_SIZE ];
+    char keyValue[ MAX_VAL_SIZE ];
+    char keyComment[ MAX_VAL_SIZE ];
+    char fitsErr[ MAX_ERR_MESSAGE_LENGTH ];
+    char* tempExtname = NULL;
+    int i;
+    int hduType = 0;
+    int status = 0;
+    int numKeys = 0;
+    psMetadataType metadataItemType;
+    
+    if ( fd == NULL ) {
+            psError( __func__, "Null FITS file descriptor not allowed" );
+            return NULL;
+        }
+        
+    if ( extname == NULL && extnum == 0 ) {
+            psError( __func__, "Null extname AND extnum = 0 not allowed" );
+            return NULL;
+        } else if ( extname && extnum ) {
+            psError( __func__, "Both extname AND extnum arguments should not have valid values." );
+            return NULL;
+        }
+        
+    // Allocate metadata if user didn't
+    if ( output == NULL ) {
+            output = psMetadataAlloc();
+            return NULL;
+        }
+        
+    // Move to user designated HDU number or HDU name in FITS file. HDU numbers starts at one.
+    if ( extname == NULL ) {
+            if ( fits_movabs_hdu( fd, extnum, &hduType, &status ) != 0 ) {
+                    fits_get_errstatus( status, fitsErr );
+                    psError( __func__, "FITS error while locating header: %s", fitsErr );
+                    status = 0;
+                    fits_close_file( fd, &status );
+                    return NULL;
+                }
+        } else if ( extnum > 0 ) {
+            tempExtname = ( char* ) psAlloc( strlen( extname ) + 1 ); // fits_movnam_hdu doesn't like const part of extname
+            strncpy( tempExtname, extname, MAX_VAL_SIZE );
+            if ( fits_movnam_hdu( fd, ANY_HDU, tempExtname, 0, &status ) != 0 ) {
+                    fits_get_errstatus( status, fitsErr );
+                    psError( __func__, "FITS error while locating header: %s", fitsErr );
+                    status = 0;
+                    fits_close_file( fd, &status );
+                    psFree( tempExtname );
+                    return NULL;
+                }
+            psFree( tempExtname );
+        }
+        
+    // Get number of key names
+    if ( fits_get_hdrpos( fd, &numKeys, NULL, &status ) != 0 ) {
+            fits_get_errstatus( status, fitsErr );
+            psError( __func__, "FITS error while reading keys: %s", fitsErr );
+            status = 0;
+            fits_close_file( fd, &status );
+            return NULL;
+        }
+        
+    // Get each key name. Keywords start at one.
+    for ( i = 1; i <= numKeys; i++ ) {
+            if ( fits_read_keyn( fd, i, keyName, keyValue, keyComment, &status ) != 0 ) {
+                    fits_get_errstatus( status, fitsErr );
+                    psError( __func__, "FITS error while reading key number %d: %s", i, fitsErr );
+                    status = 0;
+                    fits_close_file( fd, &status );
+                    return NULL;
+                }
+                
+            if ( fits_get_keytype( keyValue, &keyType, &status ) != 0 ) {
+                    fits_get_errstatus( status, fitsErr );
+                    psError( __func__, "FITS error while determining key type: %s", fitsErr );
+                    status = 0;
+                    fits_close_file( fd, &status );
+                    return NULL;
+                }
+                
+            switch ( keyType ) {
+                    case 'I':
+                    metadataItemType = PS_META_S32;
+                    success = psMetadataAdd( output, PS_LIST_HEAD, keyName, metadataItemType, keyComment, atoi( keyValue ) );
+                    break;
+                    case 'F':
+                    metadataItemType = PS_META_F64;
+                    success = psMetadataAdd( output, PS_LIST_HEAD, keyName, metadataItemType, keyComment, atof( keyValue ) );
+                    break;
+                    case 'C':
+                    metadataItemType = PS_META_STR;
+                    success = psMetadataAdd( output, PS_LIST_HEAD, keyName, metadataItemType, keyComment, keyValue );
+                    break;
+                    case 'L':
+                    case 'X':
+                    default:
+                    psError( __func__, "Invalid psMetadataType: %c", keyType );
+                    return NULL;
+                }
+                
+            if ( !success ) {
+                    psError( __func__, "Failed to add metadata item. Name: %s", keyName );
+                }
+        }
+        
+    return output;
+}
Index: /trunk/psLib/src/types/psMetadata.h
===================================================================
--- /trunk/psLib/src/types/psMetadata.h	(revision 1350)
+++ /trunk/psLib/src/types/psMetadata.h	(revision 1351)
@@ -1,18 +1,18 @@
 /** @file  psMetadata.h
- *
- *  @brief Contains metadata struuctures, enumerations and functions prototypes
- *
- *  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
- *  prototypes necessary creating psLib metadata APIs
- *
- *  @ingroup Metadata
- *
- *  @author Ross Harman, MHPCC
- *
- *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-07-29 20:16:34 $
- *
- *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
- */
+*
+*  @brief Contains metadata struuctures, enumerations and functions prototypes
+*
+*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+*  prototypes necessary creating psLib metadata APIs
+*
+*  @ingroup Metadata
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-07-30 19:37:07 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
 #ifndef PS_METADATA_H
 #define PS_METADATA_H
@@ -30,14 +30,14 @@
  */
 typedef enum {
-    PS_META_ITEM_SET = 0,               ///< Null. Metadata is in psMetadataItem.items
-    PS_META_S32,                        ///< Signed 32-bit integer data.
-    PS_META_F32,                        ///< Single-precision float data.
-    PS_META_F64,                        ///< Double-precision float data.
-    PS_META_STR,                        ///< String data (Stored in as void *).
-    PS_META_IMG,                        ///< Image data (Stored in as void *).
-    PS_META_JPEG,                       ///< JPEG data (Stored in as void .
-    PS_META_PNG,                        ///< PNG data (Stored in as void *).
-    PS_META_ASTROM,                     ///< Astrometric coefficients (Stored in as void *).
-    PS_META_UNKNOWN,                    ///< Other data (Stored in as void *).
+    PS_META_ITEM_SET = 0,                ///< Null. Metadata is in psMetadataItem.items
+    PS_META_S32,                         ///< Signed 32-bit integer data.
+    PS_META_F32,                         ///< Single-precision float data.
+    PS_META_F64,                         ///< Double-precision float data.
+    PS_META_STR,                         ///< String data (Stored in as void *).
+    PS_META_IMG,                         ///< Image data (Stored in as void *).
+    PS_META_JPEG,                        ///< JPEG data (Stored in as void .
+    PS_META_PNG,                         ///< PNG data (Stored in as void *).
+    PS_META_ASTROM,                      ///< Astrometric coefficients (Stored in as void *).
+    PS_META_UNKNOWN,                     ///< Other data (Stored in as void *).
     PS_META_NTYPE                       ///< Number of types. Must be last.
 } psMetadataType;
@@ -49,18 +49,18 @@
  */
 typedef struct psMetadataItem
-{
-    const int id;                       ///< Unique ID for metadata item.
-    char *restrict name;                ///< Name of metadata item.
-    psMetadataType type;                ///< Type of metadata item.
-    union
     {
-        psS32   S32;                    ///< Signed 32-bit integer data.
-        psF32   F32;                    ///< Single-precision float data.
-        psF64   F64;                    ///< Double-precision float data.
-        psPTR     V;                    ///< Pointer to other type of data.
-    }data;                              ///< Union for data types.
-    char *comment;                      ///< Optional comment ("", not NULL).
-    psList *restrict items;             ///< List of psMetadataItems with same name.
-}
+        const int id;                       ///< Unique ID for metadata item.
+        char *restrict name;                ///< Name of metadata item.
+        psMetadataType type;                ///< Type of metadata item.
+        union
+            {
+                psS32 S32;                    ///< Signed 32-bit integer data.
+                psF32 F32;                    ///< Single-precision float data.
+                psF64 F64;                    ///< Double-precision float data.
+                psPTR V;                    ///< Pointer to other type of data.
+            }data;                              ///< Union for data types.
+        char *comment;                      ///< Optional comment ("", not NULL).
+        psList *restrict items;             ///< List of psMetadataItems with same name.
+    }
 psMetadataItem;
 
@@ -72,8 +72,8 @@
  */
 typedef struct psMetadata
-{
-    psList *restrict list;
-    psHash *restrict table;
-}
+    {
+        psList *restrict list;
+        psHash *restrict table;
+    }
 psMetadata;
 
@@ -97,7 +97,7 @@
  */
 psMetadataItem *psMetadataItemAlloc(
-    const char *name,                   ///< Name of metadata item.
-    psMetadataType type,                ///< Type of metadata item.
-    const char *comment,                ///< Comment for metadata item.
+    const char *name,                    ///< Name of metadata item.
+    psMetadataType type,                 ///< Type of metadata item.
+    const char *comment,                 ///< Comment for metadata item.
     ...                                 ///< Arguments for name formatting and metadata item data.
 );
@@ -117,7 +117,7 @@
  */
 psMetadataItem *psMetadataItemAllocV(
-    const char *name,                   ///< Name of metadata item.
-    psMetadataType type,                ///< Type of metadata item.
-    const char *comment,                ///< Comment for metadata item.
+    const char *name,                    ///< Name of metadata item.
+    psMetadataType type,                 ///< Type of metadata item.
+    const char *comment,                 ///< Comment for metadata item.
     va_list list                        ///< Arguments for name formatting and metadata item data.
 );
@@ -140,6 +140,6 @@
  */
 bool psMetadataAddItem(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
-    int where,                          ///< Location to be added.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
+    int where,                           ///< Location to be added.
     psMetadataItem *restrict item       ///< Metadata item to be added.
 );
@@ -152,9 +152,9 @@
  */
 bool psMetadataAdd(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
-    int where,                          ///< Location to be added.
-    const char *name,                   ///< Name of metadata item.
-    psMetadataType type,                ///< Type of metadata item.
-    const char *comment,                ///< Comment for metadata item.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
+    int where,                           ///< Location to be added.
+    const char *name,                    ///< Name of metadata item.
+    psMetadataType type,                 ///< Type of metadata item.
+    const char *comment,                 ///< Comment for metadata item.
     ...                                 ///< Arguments for name formatting and metadata item data.
 );
@@ -170,6 +170,6 @@
  */
 bool psMetadataRemove(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
-    int where,                          ///< Location to be removed.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
+    int where,                           ///< Location to be removed.
     const char *restrict key            ///< Name of metadata key.
 );
@@ -183,5 +183,5 @@
  */
 psMetadataItem *psMetadataLookup(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
     const char *restrict key            ///< Name of metadata key.
 );
@@ -194,5 +194,5 @@
  */
 psMetadataItem *psMetadataGet(
-    psMetadata *restrict md,            ///< Metadata collection to insert metadat item.
+    psMetadata *restrict md,             ///< Metadata collection to insert metadat item.
     int where                           ///< Location to be retrieved.
 );
@@ -205,5 +205,5 @@
  */
 bool psMetadataSetIterator(
-    psMetadata *restrict md,            ///< Metadata collection to iterate.
+    psMetadata *restrict md,             ///< Metadata collection to iterate.
     int where                           ///< Location of iterator.
 );
@@ -216,6 +216,6 @@
  */
 psMetadataItem *psMetadataGetNext(
-    psMetadata *restrict md,            ///< Metadata collection to iterate.
-    const char *restrict match,         ///< Beginning of key name.
+    psMetadata *restrict md,             ///< Metadata collection to iterate.
+    const char *restrict match,          ///< Beginning of key name.
     int which                           ///< Iterator to be used.
 );
@@ -228,6 +228,6 @@
  */
 psMetadataItem *psMetadataGetPrevious(
-    psMetadata *restrict md,            ///< Metadata collection to iterate.
-    const char *restrict match,         ///< Beginning of key name.
+    psMetadata *restrict md,             ///< Metadata collection to iterate.
+    const char *restrict match,          ///< Beginning of key name.
     int which                           ///< Iterator to be used.
 );
@@ -244,7 +244,7 @@
  */
 void psMetadataItemPrint(
-    FILE *fd,                           ///< Pointer to file to write metadata item.
-    const char *format,                 ///< Format to print metadata item.
-    const psMetadataItem *restrict md   ///< Metadata item to print.
+    FILE *fd,                                    ///< Pointer to file to write metadata item.
+    const char *format,                          ///< Format to print metadata item.
+    const psMetadataItem *restrict metadataItem ///< Metadata item to print.
 );
 
@@ -256,7 +256,7 @@
  */
 psMetadata *psMetadataReadHeader(
-    psMetadata *output,                 ///< Resulting metadata from read.
-    const char *extname,                ///< File name extension string.
-    int extnum,                         ///< File name extension number.
+    psMetadata *output,                  ///< Resulting metadata from read.
+    const char *extname,                 ///< File name extension string.
+    int extnum,                          ///< File name extension number.
     const char *filename                ///< Name of file to read.
 );
@@ -269,8 +269,8 @@
  */
 psMetadata *psMetadataFReadHeader(
-    psMetadata *output,                 ///< Resulting metadata from read.
-    const char *extname,                ///< File name extension string.
-    int extnum,                         ///< File name extension number.
-    FILE *fd                            ///< Pointer to file to read.
+    psMetadata *output,                  ///< Resulting metadata from read.
+    const char *extname,                 ///< File name extension string.
+    int extnum,                          ///< File name extension number.
+    fitsfile *fd                        ///< Pointer to file to read.
 );
 /// @}
