Index: /trunk/src/cee/RpUnitsCInterface.cc
===================================================================
--- /trunk/src/cee/RpUnitsCInterface.cc	(revision 20)
+++ /trunk/src/cee/RpUnitsCInterface.cc	(revision 20)
@@ -0,0 +1,83 @@
+#include "../include/RpUnits.h"
+#include "../include/RpUnitsCInterface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    RpUnits* defineUnit(const char* unitSymbol, RpUnits* basis)
+    {
+        return RpUnits::define(unitSymbol, basis);
+    }
+
+    RpUnits* defineConv(    RpUnits* fromUnit,
+                            RpUnits* toUnit,
+                            double (*convForwFxnPtr)(double),
+                            double (*convBackFxnPtr)(double)    )
+    {
+        return RpUnits::define(fromUnit,toUnit,convForwFxnPtr,convBackFxnPtr);
+    }
+
+    RpUnits* find(const char* key) 
+    {
+        return RpUnits::find(key);
+    }
+
+    const char* getUnits(RpUnits* unit)
+    {
+        return unit->getUnits().c_str();
+    }
+
+    const char* getUnitsName(RpUnits* unit)
+    {
+        return unit->getUnitsName().c_str();
+    }
+
+    double getExponent(RpUnits* unit)
+    {
+        return unit->getExponent();
+    }
+
+    RpUnits* getBasis(RpUnits* unit)
+    {
+        return unit->getBasis();
+    }
+
+    int makeMetric(RpUnits* basis)
+    {
+        return RpUnits::makeMetric(basis);
+    }
+
+    const char* convert_str(    RpUnits* fromUnits, 
+                                RpUnits* toUnits, 
+                                double val,
+                                int showUnits   )
+    {
+        return convert_str_result(fromUnits,toUnits,val,showUnits,NULL);
+    }
+    
+    const char* convert_str_result( RpUnits* fromUnits, 
+                                    RpUnits* toUnits, 
+                                    double val, 
+                                    int showUnits,
+                                    int* result )
+    {
+        return fromUnits->convert(toUnits,val,showUnits,result).c_str();
+    }
+
+    double convert_double(RpUnits* fromUnits, RpUnits* toUnits, double val)
+    {
+        return convert_double_result(fromUnits,toUnits,val,NULL);
+    }
+
+    double convert_double_result(   RpUnits* fromUnits, 
+                                    RpUnits* toUnits, 
+                                    double val, 
+                                    int* result )
+    {
+        return fromUnits->convert(toUnits,val,result);
+    }
+
+#ifdef __cplusplus
+}
+#endif
Index: /trunk/src/cee/rappture_interface.c
===================================================================
--- /trunk/src/cee/rappture_interface.c	(revision 20)
+++ /trunk/src/cee/rappture_interface.c	(revision 20)
@@ -0,0 +1,739 @@
+#include "../include/rappture_interface.h"
+
+/**********************************************************************/
+// FUNCTION: PyObject* importRappture()
+/// fxn to mimic/implement the python call "import Rappture"
+/**
+ * Clients use this function to import the Rappture module into
+ *          the Python Interpretor.
+ *
+ * Notes: It is the client's responsibility to increment and 
+ *          decrement the reference count of the returned object
+ *          as needed. 
+ *
+ * Returns pointer (PyObject*) to the Rappture.library class 
+ *          if successful, or NULL if something goes wrong.
+ */
+
+
+PyObject* importRappture() 
+{
+    
+    // it is the callers responsibility to Py_DECREF the returned object 
+    // if it exists.
+
+    PyObject* pName     = NULL;
+    PyObject* pModule   = NULL;
+    PyObject* mClass    = NULL;
+    PyObject* retVal    = NULL;    /* return object */
+
+    // create a string object holding the name of the module
+    pName = PyString_FromString("Rappture");
+
+    if (pName) {
+        pModule = PyImport_Import(pName);
+        if (pModule) {
+            /* fetch module.class */
+            mClass = PyObject_GetAttrString(pModule, "library"); 
+            Py_DECREF(pModule);
+
+            if (mClass) {
+                // try to instantiate the class
+                if (PyCallable_Check(mClass)) {
+
+                    retVal = mClass;
+                    
+                }
+                else {
+                    // mClass not callable
+                    // something went wrong
+                    // python will probably raise error
+                }
+
+                // not sure if we need to increase and decrease
+                // increase because we are returning a ref to the object
+                // decrease because this function no longer needs the ref.
+                // 
+                // the decrease is left as an exercise to the calling fxn.
+                // 
+                // Py_DECREF(mClass);
+            }
+
+            // Py_DECREF(pModule);
+        }
+        else {
+            // pModule was not created
+        }
+
+        Py_DECREF(pName);
+    }
+    else {
+        // pName was not able to be created as a PyObject string
+    }       
+
+    return retVal;
+
+}  
+
+/**********************************************************************/
+// FUNCTION: PyObject* createRapptureObj(PyObject* rpObj, const char* path)
+/// fxn to mimic/implement the python call "lib = Rappture.library(".")"
+/// fxn instatiates a Rappture Object and returns it to the caller.
+/**
+ * Clients use this function to create a Rappture object which can 
+ *          access the Rappture member functions.
+ *
+ * Notes: It is the client's responsibility to increment and 
+ *          decrement the reference count of the returned object
+ *          as needed. 
+ *        
+ *        Neither of the two arguments (rpObj,path) are optional.
+ *          if either value is NULL, NULL will be returned.
+ *
+ * Returns pointer (PyObject*) to an instantiated Rappture object
+ *          if successful, or NULL if something goes wrong.
+ */
+
+PyObject* createRapptureObj (PyObject* rpObj, const char* path)
+{
+    PyObject* args      = NULL;      /* args tuple */
+    PyObject* stringarg = NULL;      /* string of arguments */
+    PyObject* lib       = NULL;      /* results from fxn call */
+    PyObject* retVal    = NULL;      /* fxn return value */
+
+
+    if (rpObj) {
+        if (path) {
+            // setup our arguments in a Python tuple
+            args = PyTuple_New(1);
+            stringarg = PyString_FromString(path);
+            PyTuple_SetItem(args, 0, stringarg);
+                    
+            // call the class ... lib = Rappture.library("...")
+            lib = PyObject_CallObject(rpObj, args);
+            
+            // following line could cause a segfault if used in place of above
+            // maybe path could == NULL or bad memory
+            // lib = PyObject_CallFunction(rpObj,"(s)", path);
+
+            if (lib) {
+                // return the Rappture instantiation.
+                retVal = lib;
+            }
+            else {
+                // lib was not successfully created
+            }
+
+            Py_DECREF(stringarg);
+            Py_DECREF(args);
+        }
+        else {
+            // path was null
+        }
+    } 
+    else {
+        // rpObj was null
+    }
+
+    return retVal;
+
+}
+
+/**********************************************************************/
+// FUNCTION: void* rpElement(PyObject* lib, const char* path, const char* flavor)
+/// fxn to mimic/implement the python call "element = lib.element("..")"
+/// fxn calls the element() member function of the Rappture.library
+///     class and returns the text to the caller
+/**
+ * Clients use this function to call the element() member function of the 
+ *          Rappture.library class and get the text of the Rappture 
+ *          object lib.
+ *
+ * Notes:   If (flavor == "object") || (flavor == NULL),
+ *          1) it is the client's responsibility to increment and 
+ *             decrement the reference count of the returned object
+ *             as needed.
+ *          2) the return object will need to be cast as a PyObject* 
+ *             to use it.
+ *
+ *          If (flavor == type) || (flavor == id) || (flavor == component),
+ *          1) the return object will need to be cast as a char*
+ *             to use it.
+ *        
+ *        The Arguments lib and pathare not optional.
+ *          If either value is NULL, NULL will be returned.
+ *
+ * Returns pointer (char*) to the c style string representing the
+ *          xml text of the Rappture object if successful, or 
+ *          NULL if something goes wrong.
+ */
+
+void* rpElement(PyObject* lib, const char* path, const char* flavor)
+{
+    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
+    PyObject* rslt      = NULL;      /* results from fxn call */
+    void* retVal        = NULL;      /* fxn return value */
+
+    if (lib && path) {
+        
+        // retrieve the lib.element() function
+        mbr_fxn = PyObject_GetAttrString(lib, "element");
+
+        if (mbr_fxn) {
+
+            if (PyCallable_Check(mbr_fxn)) {
+                
+                // call the lib.element() function with arguments
+                if (flavor) {
+                    rslt = PyObject_CallFunction(mbr_fxn,"(ss)", path, flavor);
+                }
+                else {
+                    rslt = PyObject_CallFunction(mbr_fxn,"(s)", path);
+                }
+
+                if (rslt) {
+
+                    if (flavor == NULL) {
+                        // return a PyObject*
+                        retVal = (void*) rslt;
+                    }
+                    else if((*flavor == 'o')&&(strncmp(flavor,"object", 6)==0)){
+                        // return a PyObject*
+                        retVal = (void*) rslt;
+                    }
+                    else if ( 
+                      ((*flavor == 't')&&(strncmp(flavor,"type", 4) == 0)) 
+                    ||((*flavor == 'i')&&(strncmp(flavor,"id", 2) == 0))
+                    ||((*flavor == 'c')&&(strncmp(flavor,"component", 9) == 0)))
+                    {
+                        // return a char*
+                        // convert the result to c style strings
+                        retVal = (void*) PyString_AsString(rslt);
+                        Py_DECREF(rslt);
+                    }
+                    else {
+                        // unrecognized format
+                    }
+                    
+                    // Py_DECREF(rslt);
+
+                } // rslt was null
+                
+            } // mbr_fxn was not callable
+            
+            Py_DECREF(mbr_fxn);
+        } // mbr_fxn was null
+    }
+    else {
+        // lib or path was set to NULL
+    }
+
+    return retVal;
+}
+
+
+/**********************************************************************/
+// FUNCTION: void** rpChildren(PyObject* lib, const char* path, const char* flavor)
+/// fxn to mimic/implement the python call "xmlText = lib.children("..")"
+/// fxn calls the element() member function of the Rappture.library
+///     class and returns the text to the caller
+/**
+ * Clients use this function to call the xml() member function of the 
+ *          Rappture.library class and get the text of the Rappture 
+ *          object lib.
+ *
+ * Notes:   If (flavor == "object") || (flavor == NULL),
+ *          1) it is the client's responsibility to increment and 
+ *             decrement the reference count of the returned object
+ *             as needed.
+ *          2) the return object will need to be cast as a PyObject* 
+ *             to use it.
+ *
+ *          If (flavor == "type")||(flavor == "id")||(flavor == "component"),
+ *          1) the return object will need to be case as a char*
+ *             to use it.
+ *        
+ *        The Arguments lib and pathare not optional.
+ *          If either value is NULL, NULL will be returned.
+ *
+ * Returns pointer (char*) to the c style string representing the
+ *          xml text of the Rappture object if successful, or 
+ *          NULL if something goes wrong.
+ */
+
+void** rpChildren(PyObject* lib, const char* path, const char* flavor)
+{
+    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
+    PyObject* rslt      = NULL;      /* results from fxn call */
+    PyObject* list_item = NULL;      /* item from list of returned children */
+//    void* retVal        = NULL;      /* fxn return value */
+    int list_size       = 0;
+    int index           = 0;
+    char** rslt_arr_c   = NULL;
+    void** rslt_arr  = NULL;
+
+    if (lib && path) {
+        
+        // retrieve the lib.children() function
+        mbr_fxn = PyObject_GetAttrString(lib, "children");
+
+        if (mbr_fxn) {
+
+            if (PyCallable_Check(mbr_fxn)) {
+                
+                // call the lib.element() function with arguments
+                if (flavor) {
+                    rslt = PyObject_CallFunction(mbr_fxn,"(ss)", path, flavor);
+                }
+                else {
+                    rslt = PyObject_CallFunction(mbr_fxn,"(s)", path);
+                }
+
+                if (rslt) {
+
+                    if (flavor == NULL) {
+                        // return a PyObject*
+                        // retVal = (void*) rslt;
+                        // 
+                        // the PyObject* points to a list, so we need to
+                        // convert this to an array of char*'s
+
+                        list_size = PyList_Size(rslt);
+                        rslt_arr = (void**) calloc(list_size+1,sizeof(void*));
+                        if (rslt_arr) {
+                            while (index < list_size) {
+                                // list_item is a borrowed reference
+                                list_item = PyList_GetItem(rslt,index);
+                                rslt_arr[index] = (void*) (list_item);
+                                index++;
+                            }
+                            // *(rslt_arr[index]) = (void*)NULL;
+                        }
+                    }
+                    else if((*flavor == 'o')&&(strncmp(flavor,"object", 6)==0)){
+                        // return a PyObject*
+                        // retVal = (void*) rslt;
+                        // 
+                        // the PyObject* points to a list, so we need to
+                        // convert this to an array of char*'s
+
+                        list_size = PyList_Size(rslt);
+                        rslt_arr = (void**) calloc(list_size+1,sizeof(void*));
+                        if (rslt_arr) {
+                            while (index < list_size) {
+                                // list_item is a borrowed reference
+                                list_item = PyList_GetItem(rslt,index);
+                                rslt_arr[index] = (void*) (list_item);
+                                index++;
+                            }
+                            // *(rslt_arr[index]) = NULL;
+                        }
+                    }
+                    else if ( 
+                      ((*flavor == 't')&&(strncmp(flavor,"type", 4) == 0)) 
+                    ||((*flavor == 'i')&&(strncmp(flavor,"id", 2) == 0))
+                    ||((*flavor == 'c')&&(strncmp(flavor,"component", 9) == 0)))
+                    {
+                        // the PyObject* points to a list, so we need to
+                        // convert this to an array of char*'s
+
+                        list_size = PyList_Size(rslt);
+                        rslt_arr_c = (char**) calloc(list_size+1,sizeof(char*));
+                        if (rslt_arr_c) {
+                            while (index < list_size) {
+                                // list_item is a borrowed reference
+                                list_item = PyList_GetItem(rslt,index);
+                                // we cannot deallocate the results of 
+                                // PyString_AsString()
+                                rslt_arr_c[index] = PyString_AsString(list_item);
+                                index++;
+                                
+                            }
+                            // *(rslt_arr[index]) = NULL;
+                            rslt_arr = (void**) rslt_arr_c;
+                        }
+                        // return a char*
+                        // convert the result to c style strings
+                        // retVal = (void*) PyString_AsString(rslt);
+                        Py_DECREF(rslt);
+                    }
+                    else {
+                        // unrecognized format
+                    }
+                    
+                    // Py_DECREF(rslt);
+
+                } // rslt was null
+                
+            } // mbr_fxn was not callable
+            
+            Py_DECREF(mbr_fxn);
+        } // mbr_fxn was null
+    }
+    else {
+        // lib or path was set to NULL
+    }
+
+    // return retVal;
+    return (void**) rslt_arr;
+}
+
+/**********************************************************************/
+// FUNCTION: PyObject* rpChildren_f(PyObject* lib, const char* path, const char* flavor)
+/// fxn to mimic/implement the python call "xmlText = lib.children("..")"
+/// fxn calls the element() member function of the Rappture.library
+///     class and returns the text to the caller
+/**
+ * Clients use this function to call the xml() member function of the 
+ *          Rappture.library class and get the text of the Rappture 
+ *          object lib.
+ *
+ * Notes:   If (flavor == "object") || (flavor == NULL),
+ *          1) it is the client's responsibility to increment and 
+ *             decrement the reference count of the returned object
+ *             as needed.
+ *          2) the return object will need to be cast as a PyObject* 
+ *             to use it.
+ *
+ *          If (flavor == "type")||(flavor == "id")||(flavor == "component"),
+ *          1) the return object will need to be case as a char*
+ *             to use it.
+ *        
+ *        The Arguments lib and pathare not optional.
+ *          If either value is NULL, NULL will be returned.
+ *
+ * Returns pointer (char*) to the c style string representing the
+ *          xml text of the Rappture object if successful, or 
+ *          NULL if something goes wrong.
+ */
+
+PyObject* rpChildren_f(PyObject* lib, const char* path, const char* flavor)
+{
+    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
+    PyObject* rslt      = NULL;      /* results from fxn call */
+//    PyObject* list_item = NULL;      /* item from list of returned children */
+//    void* retVal        = NULL;      /* fxn return value */
+//    int list_size       = 0;
+//    int index           = 0;
+//    char** rslt_arr_c   = NULL;
+//    void** rslt_arr  = NULL;
+
+//    char* xmlChild = NULL;
+
+    if (lib && path) {
+        
+        // retrieve the lib.children() function
+        mbr_fxn = PyObject_GetAttrString(lib, "children");
+
+        if (mbr_fxn) {
+
+            if (PyCallable_Check(mbr_fxn)) {
+                
+                // call the lib.children() function with arguments
+                if (flavor) {
+                    rslt = PyObject_CallFunction(mbr_fxn,"(ss)", path, flavor);
+                }
+                else {
+                    rslt = PyObject_CallFunction(mbr_fxn,"(s)", path);
+                }
+
+                /*
+                if (rslt) {
+                    list_size = PyList_Size(rslt);
+                    while (index < list_size) {
+                        // list_item is a borrowed reference
+                        list_item = PyList_GetItem(rslt,index);
+                        // we cannot deallocate the results of 
+                        // PyString_AsString()
+                        // printf("list item = :%x:\n", list_item);
+                        xmlChild = PyString_AsString(list_item);
+                        printf("xml = :%s:\n",xmlChild);
+                        index++;
+                    }
+                }
+                */
+
+                /*
+                if (rslt) {
+                    list_item = PyList_GetItem(rslt,0);
+                    xmlChild = PyString_AsString(list_item);
+                    printf("xml0 = :%s:\n",xmlChild);
+                    list_item = PyList_GetItem(rslt,1);
+                    xmlChild = PyString_AsString(list_item);
+                    printf("xml1 = :%s:\n",xmlChild);
+                } // rslt was null
+                */
+                
+            } // mbr_fxn was not callable
+            
+            Py_DECREF(mbr_fxn);
+        } // mbr_fxn was null
+    }
+    else {
+        // lib or path was set to NULL
+    }
+
+    return rslt;
+}
+
+/**********************************************************************/
+// FUNCTION: const char* rpGet(PyObject* lib, const char* path)
+/// fxn to mimic/implement the python call "xmlText = lib.get('...')"
+/// fxn calls the get() member function of the Rappture.library class
+///     and returns the text to the caller
+/**
+ * Clients use this function to call the get() member function of the 
+ *          Rappture.library class and get the text of the Rappture 
+ *          object lib.
+ *
+ * Notes: The argument (lib) is not optional. If it is NULL, 
+ *          NULL will be returned.
+ *
+ * Returns pointer (const char*) to the c style string representing the
+ *          xml text provided by the path of the Rappture object if 
+ *          successful, or NULL if something goes wrong.
+ *
+ *          The return value's contents should not be changed because 
+ *          it is a pointer being borrowed from python's buffer space
+ *          (hence the _const_)
+ */
+const char* rpGet(PyObject* lib, const char* path)
+{
+    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
+    PyObject* rslt      = NULL;      /* results from fxn call */
+    char* retVal        = NULL;      /* return value */
+
+    if (lib) {
+        // retrieve the lib.get() function
+        mbr_fxn = PyObject_GetAttrString(lib, "get");
+
+        if (mbr_fxn) {
+
+            if (PyCallable_Check(mbr_fxn)) {
+                
+                // call the lib.get() function
+                rslt = PyObject_CallFunction(mbr_fxn,"(s)", path);
+                if (rslt) {
+                    // convert the result to c style strings
+                    retVal = PyString_AsString(rslt);
+                    // Py_DECREF(rslt);
+                }
+                
+            }
+            Py_DECREF(mbr_fxn);
+        }
+    }
+    else {
+        // lib was set to NULL
+    }
+
+    return (const char*) retVal;
+    
+}
+
+/**********************************************************************/
+// FUNCTION: void rpPut( PyObject* lib, 
+//                       const char* path, 
+//                       const char* value, 
+//                       const char* id, 
+//                       int append)
+/// fxn to mimic/implement the python call "lib.put('...')"
+/// fxn calls the put() member function of the Rappture.library class
+///     and creates user specified fields within xml document
+/**
+ * Clients use this function to call the put() member function of the 
+ *          Rappture.library class and place custom text into the 
+ *          Rappture object lib.
+ *
+ * Notes: The argument (lib) is not optional. If it is NULL, 
+ *          NULL will be returned.
+ *
+ * Returns nothing.
+ */
+void rpPut( PyObject* lib, 
+            const char* path, 
+            const char* value, 
+            const char* id, 
+            int append )
+{
+    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
+
+    if (lib) {
+        // retrieve the lib.xml() function
+        mbr_fxn = PyObject_GetAttrString(lib, "put");
+
+        if (mbr_fxn) {
+
+            if (PyCallable_Check(mbr_fxn)) {
+                PyObject_CallFunction(mbr_fxn,"(sssi)",path,value,id,append);
+            }
+            Py_DECREF(mbr_fxn);
+        }
+    }
+    else {
+        // lib was set to NULL
+    }
+
+}
+
+/**********************************************************************/
+// FUNCTION: void rpPutObj( PyObject* lib, 
+//                       const char* path, 
+//                       const char* value, 
+//                       const char* id, 
+//                       int append)
+/// fxn to mimic/implement the python call "lib.put('...')"
+/// fxn calls the put() member function of the Rappture.library class
+///     and creates user specified fields within xml document
+/**
+ * Clients use this function to call the put() member function of the 
+ *          Rappture.library class and place custom text into the 
+ *          Rappture object lib.
+ *
+ * Notes: The argument (lib) is not optional. If it is NULL, 
+ *          NULL will be returned.
+ *
+ * Returns nothing.
+ */
+void rpPutObj( PyObject* lib, 
+            const char* path, 
+            PyObject* value, 
+            const char* id, 
+            int append )
+{
+    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
+
+    if (lib) {
+        // retrieve the lib.xml() function
+        mbr_fxn = PyObject_GetAttrString(lib, "put");
+
+        if (mbr_fxn) {
+
+            if (PyCallable_Check(mbr_fxn)) {
+                PyObject_CallFunction(mbr_fxn,"(sOsi)",path,value,id,append);
+                // PyObject_CallFunctionObjArgs(mbr_fxn,path,value,id,append,NULL);
+            }
+            Py_DECREF(mbr_fxn);
+        }
+    }
+    else {
+        // lib was set to NULL
+    }
+
+}
+
+/**********************************************************************/
+// FUNCTION: PyObject* rpRemove(PyObject* lib, const char* path)
+/// fxn to mimic/implement the python call "lib.remove('...')"
+/// fxn calls the remove() member function of the Rappture.library class
+///     and removes the elements listed, if they exist
+/**
+ * Clients use this function to call the remove() member function of the 
+ *          Rappture.library class and remove the elements of the 
+ *          Rappture object lib.
+ *
+ * Notes: The argument (lib) is not optional. If it is NULL, 
+ *          NULL will be returned.
+ *
+ * Returns nothin.
+ *
+ */
+PyObject* rpRemove(PyObject* lib, const char* path)
+{
+    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
+    PyObject* rslt      = NULL;      /* results from fxn call */
+    
+//    PyObject* args = NULL;
+//    PyObject* stringarg = NULL;
+
+
+    if (lib) {
+        // retrieve the lib.remove() function
+        mbr_fxn = PyObject_GetAttrString(lib, "remove");
+
+        if (mbr_fxn) {
+
+            if (PyCallable_Check(mbr_fxn)) {
+
+                // setup our arguments in a Python tuple
+                // args = PyTuple_New(1);
+                // stringarg = PyString_FromString(path);
+                // PyTuple_SetItem(args, 0, stringarg);
+
+                // call the class ... lib = Rappture.library("...")
+                // rslt = PyObject_CallObject(mbr_fxn, args);
+
+                
+                // call the lib.xml() function with no arguments
+                rslt = PyObject_CallFunction(mbr_fxn,"(s)", path);
+                // it is caller's responsibility to adjust reference count
+                // Py_DECREF(rslt);
+                
+            }
+            Py_DECREF(mbr_fxn);
+        }
+    }
+    else {
+        // lib was set to NULL
+    }
+
+    return rslt;
+    
+}
+
+/**********************************************************************/
+// FUNCTION: const char* rpXml(PyObject* lib)
+/// fxn to mimic/implement the python call "xmlText = lib.xml()"
+/// fxn calls the xml() member function of the Rappture.library class
+///     and returns the text to the caller
+/**
+ * Clients use this function to call the xml() member function of the 
+ *          Rappture.library class and get the text of the Rappture 
+ *          object lib.
+ *
+ * Notes: The argument (lib) is not optional. If it is NULL, 
+ *          NULL will be returned.
+ *
+ * Returns pointer (const char*) to the c style string representing the
+ *          xml text of the Rappture object if successful, or 
+ *          NULL if something goes wrong.
+ *
+ *          The return value's contents should not be changed because 
+ *          it is a pointer being borrowed from python's buffer space
+ *          (hence the _const_)
+ */
+
+
+const char* rpXml(PyObject* lib)
+{
+    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
+    PyObject* rslt      = NULL;      /* results from fxn call */
+    char* retVal        = NULL;      /* return value */
+
+    if (lib) {
+        // retrieve the lib.xml() function
+        mbr_fxn = PyObject_GetAttrString(lib, "xml");
+
+        if (mbr_fxn) {
+
+            if (PyCallable_Check(mbr_fxn)) {
+                
+                // call the lib.xml() function
+                rslt = PyObject_CallFunction(mbr_fxn,NULL);
+                if (rslt) {
+                    // convert the result to c style strings
+                    retVal = PyString_AsString(rslt);
+                    Py_DECREF(rslt);
+                }
+                
+            }
+            Py_DECREF(mbr_fxn);
+        }
+    }
+    else {
+        // lib was set to NULL
+    }
+
+    return (const char*) retVal;
+    
+}
Index: /trunk/src/core/RpDict.cc
===================================================================
--- /trunk/src/core/RpDict.cc	(revision 20)
+++ /trunk/src/core/RpDict.cc	(revision 20)
@@ -0,0 +1,693 @@
+/*
+#ifndef _RpDICT_H
+    #include "../include/RpDict.h"
+#endif
+*/
+
+/**************************************************************************/
+
+
+// public RpDict member functions
+
+
+/**************************************************************************
+ *
+ * int RpDict::size()
+ *  retrieve the size of the structure
+ *
+ * Results:
+ *  Returns size of the hash table
+ *
+ * Side Effects:
+ *  none.
+ * 
+ *
+ *************************************************************************/
+
+template <typename KeyType, typename ValType> 
+const int 
+RpDict<KeyType,ValType>::size() const
+{
+    return numEntries;
+}
+
+
+/**************************************************************************
+ *
+ * RpDict::set()
+ *  checks to make sure the table exists. 
+ *  places a key/value pair into the hash table
+ *
+ * Results:
+ *  Returns a reference to the RpDict object allowing the user to chain 
+ *  together different commands such as 
+ *      rpdict_obj.set(key).find(a).erase(a);
+ *
+ * Side Effects:
+ *  if successful, the hash table will have a new entry
+ * 
+ *
+ *************************************************************************/
+template <typename KeyType, typename ValType> 
+RpDict<KeyType,ValType>& 
+RpDict<KeyType,ValType>::set(   KeyType& key, 
+                                ValType& value, 
+                                int* newPtr)
+{
+    RpDictEntry<KeyType,ValType> *hPtr;
+    unsigned int hash;
+    int index;
+
+    assert(&key);
+    assert(&value);
+    
+    // take care of the case where we are creating a NULL key entry.
+    if (&key) {
+        hash = (unsigned int) hashFxn(&key);
+    }
+    else {
+        hash = 0;
+    }
+
+    index = randomIndex(hash);
+
+    /*
+     * Search all of the entries in the appropriate bucket.
+     */
+    for (hPtr = buckets[index]; hPtr != NULL; hPtr = hPtr->nextPtr) {
+        if (hash != (unsigned int) hPtr->hash) {
+            continue;
+        }
+        // if element already exists in hash, it should not be re-entered 
+        if (key == *(hPtr->getKey())){
+
+            // adjust the new flag if it was provided
+            if (newPtr) {
+                *newPtr = 0;
+            }
+
+            // adjust the value if it was provided
+            // memory management is left as an exercize for the caller
+            if (&value) {
+                hPtr->setValue(value);
+            }
+            
+            // return a reference to the dictionary object
+            return *this;
+        }
+    }
+
+    /*
+     * Entry not found.  Add a new one to the bucket.
+     */
+
+    if (newPtr) {
+        *newPtr = 1;
+    }
+
+    hPtr = new RpDictEntry<KeyType,ValType>(key,value);
+    // hPtr->setValue(value);
+    //
+    // this is just a pointer that was allocated on the heap
+    // it wont stick with the RpDictEntry after the fxn exits...
+    // need to fix still.
+    hPtr->tablePtr = this;
+    hPtr->hash = hash;
+    hPtr->nextPtr = buckets[index];
+    buckets[index] = hPtr;
+    numEntries++;
+
+    /*
+     * If the table has exceeded a decent size, rebuild it with many
+     * more buckets.
+     */
+
+    if (numEntries >= rebuildSize) {
+        RebuildTable();
+    }
+
+    // return a reference to the original object
+    return *this;
+}
+
+
+/*  
+ *----------------------------------------------------------------------
+ *  
+ *  RpDict::find(const char *key)
+ *  
+ *  Given a hash table find the entry with a matching key.
+ *  
+ * Results:
+ *  The return value is a token for the matching entry in the
+ *  hash table, or NULL if there was no matching entry.
+ *  
+ * Side effects:
+ *  None.
+ *          
+ *----------------------------------------------------------------------
+ */     
+        
+template <typename KeyType, typename ValType>
+RpDictEntry<KeyType,ValType>& 
+RpDict<KeyType,ValType>::find(KeyType& key)
+{       
+    RpDictEntry<KeyType,ValType> *hPtr;
+    unsigned int hash;
+    int index;
+
+    assert(&key);
+
+    // take care of the case where we are creating a NULL key entry.
+    if (&key) {
+        hash = (unsigned int) hashFxn(&key);
+    }
+    else {
+        hash = 0;
+    }
+
+    index = randomIndex(hash);
+
+    /*
+     * Search all of the entries in the appropriate bucket.
+     */
+
+    for (hPtr = buckets[index]; hPtr != NULL; hPtr = hPtr->nextPtr) {
+        if (hash != (unsigned int) hPtr->hash) {
+            continue;
+        }
+        if (key == *(hPtr->getKey())) {
+            // return a reference to the found object
+            return *hPtr;
+        }
+    }
+
+    // return a reference to the null object
+    // find is not supposed to return a const, but i dont want the user
+    // changing this entry's data members... what to do?
+    return *nullEntry;
+
+}
+
+
+
+/**************************************************************************
+ *
+ * virtual RpDict& RpDictIterator::getTable()
+ *  send the search iterator to the beginning of the hash table
+ *
+ * Results:
+ *  returns pointer to the first hash entry of the hash table.
+ *
+ * Side Effects:
+ *  moves iterator to the beginning of the hash table.
+ * 
+ *
+ *************************************************************************/
+/*
+template <typename KeyType,typename ValType>
+RpDict<KeyType,ValType>& 
+RpDictIterator<KeyType,ValType>::getTable() 
+{
+    return tablePtr;
+}
+*/
+
+/**************************************************************************
+ *
+ * virtual RpDictEntry& RpDict::first()
+ *  send the search iterator to the beginning of the hash table
+ *
+ * Results:
+ *  returns pointer to the first hash entry of the hash table.
+ *
+ * Side Effects:
+ *  moves iterator to the beginning of the hash table.
+ * 
+ *
+ *************************************************************************/
+template <typename KeyType,typename ValType>
+RpDictEntry<KeyType,ValType>* 
+RpDictIterator<KeyType,ValType>::first()
+{
+    srchNextIndex = 0;
+    srchNextEntryPtr = NULL;
+    return next();
+}
+
+/**************************************************************************
+ *
+ * Tcl_HashEntry * RpDict::next()
+ *  send the search iterator to the next entry of the hash table
+ *
+ * Results:
+ *  returns pointer to the next hash entry of the hash table.
+ *  if iterator is at the end of the hash table, NULL is returned
+ *  and the iterator is left at the end of the hash table.
+ *
+ * Side Effects:
+ *  moves iterator to the next entry of the hash table if it exists.
+ * 
+ *
+ *************************************************************************/
+
+template <typename KeyType,typename ValType>
+RpDictEntry<KeyType,ValType>* 
+RpDictIterator<KeyType,ValType>::next() 
+{
+    RpDictEntry<KeyType,ValType>* hPtr;
+
+    while (srchNextEntryPtr == NULL) {
+        if (srchNextIndex >= tablePtr.numBuckets) {
+            return NULL;
+        }
+        srchNextEntryPtr = tablePtr.buckets[srchNextIndex];
+        srchNextIndex++;
+    }
+    hPtr = srchNextEntryPtr;
+    srchNextEntryPtr = hPtr->nextPtr;
+
+    return hPtr;
+}
+
+/**************************************************************************
+ *
+ * RpDict & clear()
+ *  iterate through the table and call erase on each element
+ *
+ * Results:
+ *  empty hash table
+ *
+ * Side Effects:
+ *  every element of the hash table will be erased.
+ * 
+ *
+ *************************************************************************/
+template <typename KeyType, typename ValType>
+RpDict<KeyType,ValType>& 
+RpDict<KeyType,ValType>::clear() 
+{
+    RpDictEntry<KeyType,ValType> *hPtr;
+    RpDictIterator<KeyType,ValType> iter((RpDict&)*this);
+
+    hPtr = iter.first();
+
+    while (hPtr) {
+        hPtr->erase();
+        hPtr = iter.next();
+    }
+
+    return *this;
+}
+
+/**************************************************************************
+ *
+ * RpDict & getNullEntry()
+ *  get the nullEntry hash entry for initialization of references
+ *  
+ *
+ * Results:
+ *  nullEntry RpDictEntry related to this dictionary is returned
+ *
+ * Side Effects:
+ *  none
+ * 
+ *
+ *************************************************************************/
+template <typename KeyType, typename ValType>
+RpDictEntry<KeyType,ValType>& 
+RpDict<KeyType,ValType>::getNullEntry() 
+{
+    return *nullEntry;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * void RpDictEntry::erase()
+ *
+ *  Remove a single entry from a hash table.
+ *
+ * Results:
+ *  None.
+ *
+ * Side effects:
+ *  The entry given by entryPtr is deleted from its table and
+ *  should never again be used by the caller.  It is up to the
+ *  caller to free the clientData field of the entry, if that
+ *  is relevant.
+ *
+ *----------------------------------------------------------------------
+ */
+
+template <typename KeyType, typename ValType>
+void  
+RpDictEntry<KeyType,ValType>::erase()
+{   
+    RpDictEntry<KeyType,ValType> *prevPtr;
+    RpDictEntry<KeyType,ValType> **bucketPtr;
+    int index = 0;
+
+    // check to see if the object is associated with a table
+    // if object is not associated with a table, there is no 
+    // need to try to remove it from the table.
+    if (tablePtr) {
+
+        index = tablePtr->randomIndex(hash);
+    
+        // calculate which bucket the entry should be in.
+        bucketPtr = &(tablePtr->buckets[index]);
+
+        // remove the entry from the buckets
+        // 
+        // if entry is the first entry in the bucket
+        // move the bucket to point to the next entry
+        if ((*bucketPtr)->key == this->key) {
+            *bucketPtr = nextPtr;
+        }
+        else {
+            // if the entry is not the first entry in the bucket
+            // search for the entry 
+            for (prevPtr = *bucketPtr; ; prevPtr = prevPtr->nextPtr) {
+
+                // printf("malformed bucket chain in RpDictEntry::erase()");
+                assert(prevPtr != NULL);
+
+                if (prevPtr->nextPtr == this) {
+                    prevPtr->nextPtr = nextPtr;
+                    break;
+                } 
+            } // end for loop
+        } // end else
+
+        // update our table's information
+        tablePtr->numEntries--;
+
+    } // end if tablePtr
+
+    // invalidate the object
+    nextPtr = NULL;
+    tablePtr = NULL;
+    hash = 0;
+    // clientData = NULL;
+    // key = NULL;
+    
+    // delete the object.
+    // printf("delete %x\n", (unsigned) this);
+    delete this;
+    
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * const char* RpDictEntry::getKey() const
+ *
+ *  retrieve the key of the current object
+ *
+ * Results:
+ *  the key is returned to the caller
+ *
+ * Side effects:
+ *  None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+template <typename KeyType, typename ValType>
+const KeyType*
+RpDictEntry<KeyType,ValType>::getKey() const
+{   
+    return (const KeyType*) &key;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * const char* RpDictEntry::getValue() const
+ *
+ *  retrieve the value of the current object
+ *
+ * Results:
+ *  the value is returned to the caller
+ *
+ * Side effects:
+ *  None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+template <typename KeyType, typename ValType>
+const ValType* 
+RpDictEntry<KeyType,ValType>::getValue() const
+{   
+    return (const ValType*) &clientData;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * const void* RpDictEntry::setValue()
+ *
+ *  retrieve the value of the current object
+ *
+ * Results:
+ *  the value is returned to the caller
+ *
+ * Side effects:
+ *  None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+template <typename KeyType, typename ValType>
+const ValType*
+RpDictEntry<KeyType,ValType>::setValue(const ValType& value)
+{   
+    clientData = value;
+    return (const ValType*) &clientData;
+}
+
+template <typename KeyType, typename ValType>
+RpDictEntry<KeyType,ValType>::operator int() const
+{
+
+    if (!tablePtr && hash == 0)
+        return 0;
+    else
+        return 1;
+
+//    return (key);
+}
+
+
+/*************************************************************************/
+/*************************************************************************/
+
+// private member functions
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RebuildTable --
+ *
+ *  This procedure is invoked when the ratio of entries to hash
+ *  buckets becomes too large.  It creates a new table with a
+ *  larger bucket array and moves all of the entries into the
+ *  new table.
+ *
+ * Results:
+ *  None.
+ *
+ * Side effects:
+ *  Memory gets reallocated and entries get re-hashed to new
+ *  buckets.
+ *
+ *----------------------------------------------------------------------
+ */
+
+template <typename KeyType, typename ValType>
+void 
+RpDict<KeyType,ValType>::RebuildTable()
+{
+    int oldSize=0, count=0, index=0; 
+    RpDictEntry<KeyType,ValType> **oldBuckets;
+    RpDictEntry<KeyType,ValType> **oldChainPtr, **newChainPtr;
+    RpDictEntry<KeyType,ValType> *hPtr;
+    
+    void *key;
+
+    oldSize = numBuckets;
+    oldBuckets = buckets;
+
+    /*
+     * Allocate and initialize the new bucket array, and set up
+     * hashing constants for new array size.
+     */
+
+
+    numBuckets *= 4;
+
+    buckets = (RpDictEntry<KeyType,ValType> **) malloc((unsigned)
+        (numBuckets * sizeof(RpDictEntry<KeyType,ValType> *)));
+
+    for (count = numBuckets, newChainPtr = buckets;
+        count > 0; 
+        count--, newChainPtr++) {
+
+        *newChainPtr = NULL;
+    }
+
+    rebuildSize *= 4;
+    downShift -= 2;
+    mask = (mask << 2) + 3;
+
+    /*
+     * Rehash all of the existing entries into the new bucket array.
+     */
+
+    for (oldChainPtr = oldBuckets; oldSize > 0; oldSize--, oldChainPtr++) {
+        for (hPtr = *oldChainPtr; hPtr != NULL; hPtr = *oldChainPtr) {
+            *oldChainPtr = hPtr->nextPtr;
+
+            key = (void *) hPtr->getKey();
+
+            index = randomIndex(hPtr->hash);
+
+            hPtr->nextPtr = buckets[index];
+            buckets[index] = hPtr;
+        }
+    }
+
+    /*
+     * Free up the old bucket array, if it was dynamically allocated.
+     */
+
+    if (oldBuckets != staticBuckets) {
+        free((char *) oldBuckets);
+    }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hashFxn --
+ *
+ *  Compute a one-word summary of a text string, which can be
+ *  used to generate a hash index.
+ *
+ * Results:
+ *  The return value is a one-word summary of the information in
+ *  string.
+ *
+ * Side effects:
+ *  None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+template <typename KeyType, typename ValType>
+unsigned int 
+RpDict<KeyType,ValType>::hashFxn(const void *keyPtr) const
+{
+    const char *stopAddr = (const char *) keyPtr + sizeof(&keyPtr) - 1 ;
+    const char *str = (const char *) keyPtr;
+    unsigned int result;
+    int c;
+
+    result = 0;
+
+    while (str != stopAddr) {
+        c = *str;
+        result += (result<<3) + c;
+        str++;
+    }
+    
+    return result;
+}
+
+/*
+ * I tried a zillion different hash functions and asked many other
+ * people for advice.  Many people had their own favorite functions,
+ * all different, but no-one had much idea why they were good ones.
+ * I chose the one below (multiply by 9 and add new character)
+ * because of the following reasons:
+ * 
+ * 1. Multiplying by 10 is perfect for keys that are decimal strings,
+ *    and multiplying by 9 is just about as good.
+ * 2. Times-9 is (shift-left-3) plus (old).  This means that each
+ *    character's bits hang around in the low-order bits of the
+ *    hash value for ever, plus they spread fairly rapidly up to
+ *    the high-order bits to fill out the hash value.  This seems
+ *    works well both for decimal and non-decimal strings.
+ */ 
+
+
+template <typename KeyType, typename ValType>
+unsigned int 
+RpDict<KeyType,ValType>::hashFxn(std::string* keyPtr) const
+{
+    const char *str = (const char *) (keyPtr->c_str());
+    unsigned int result;
+    int c;
+
+    result = 0;
+
+    while (1) {
+        c = *str;
+        if (c == 0) {
+            break;
+        }
+        result += (result<<3) + c;
+        str++;
+    }
+    
+    return result;
+}
+
+template <typename KeyType, typename ValType>
+unsigned int 
+RpDict<KeyType,ValType>::hashFxn(char* keyPtr) const
+{
+    const char *str = (const char *) (keyPtr);
+    unsigned int result;
+    int c;
+
+    result = 0;
+
+    while (1) {
+        c = *str;
+        if (c == 0) {
+            break;
+        }
+        result += (result<<3) + c;
+        str++;
+    }
+    
+    return result;
+}
+
+/*
+ * ---------------------------------------------------------------------
+ *
+ * int RpDict::randomIndex(hash) 
+ *
+ * The following macro takes a preliminary integer hash value and
+ * produces an index into a hash tables bucket list.  The idea is
+ * to make it so that preliminary values that are arbitrarily similar
+ * will end up in different buckets.  The hash function was taken
+ * from a random-number generator.
+ *
+ * ---------------------------------------------------------------------
+ */
+
+template <typename KeyType, typename ValType>
+int 
+RpDict<KeyType,ValType>::randomIndex(unsigned int hash) 
+{
+    return (((((long) (hash))*1103515245) >> downShift) & mask);
+}
+
+
Index: /trunk/src/core/RpUnits.cc
===================================================================
--- /trunk/src/core/RpUnits.cc	(revision 20)
+++ /trunk/src/core/RpUnits.cc	(revision 20)
@@ -0,0 +1,986 @@
+ #ifndef _RpUNITS_H
+     #include "../include/RpUnits.h"
+ #endif
+
+// dict pointer
+// RpDict<std::string,RpUnits*> RpUnits::dict = RpDict<std::string,RpUnits*>();
+RpDict<std::string,RpUnits*>* RpUnits::dict = new RpDict<std::string,RpUnits*>();
+
+
+/************************************************************************
+ *                                                                      
+ * add RpUnits Object                                                   
+ *                                                                      
+ ************************************************************************/
+
+RpUnits * RpUnits::define(const std::string units, RpUnits * basis)
+{ 
+    RpUnits * newRpUnit = NULL;
+
+    if (units == "") {
+        // raise error, user sent null units!
+        return NULL;
+    }
+
+    // check to see if the user is trying to trick me!
+    if ( (basis) && (units == basis->getUnits()) ) {
+        // dont trick me!
+        return NULL;
+    }
+
+    // char * cmpPtr = NULL;
+    double exp = 0.0;
+    double oldExponent = 0;
+    double newExponent = 0;
+    int digiSearch = 0; // flag to show we are searching digits
+    int alphaSearch = 0; // flag to show we are searching chars
+    std::string dbText = "";
+
+    std::string cmpStr = "";
+    int cmpIndex = 0;
+
+    std::string::size_type length = units.length();
+    int srchIndex = length;
+    std::string srchStr = units;
+
+    // unit* p = NULL;
+
+    while ((srchStr.length() > 0)) {
+
+        srchIndex--;
+ 
+        if (srchIndex < 0) {
+            break;
+        }
+ 
+        if     ( isdigit(srchStr[srchIndex]) && !digiSearch && !alphaSearch) {
+            digiSearch = 1;
+        }
+        else if(!isdigit(srchStr[srchIndex]) &&  digiSearch && !alphaSearch) {
+ 
+            // convert our exponent to integer
+ 
+            // check to see if there is a + or - sign
+            if (  ( srchStr[srchIndex] == '+' )
+               || ( srchStr[srchIndex] == '-' ) ) {
+ 
+                // evaluate a '+' or '-' sign with the value
+                srchIndex--;
+            }
+ 
+            srchIndex++;
+ 
+            exp = atoi(&srchStr[srchIndex]);
+ 
+            // we are no longer in a digit search
+            digiSearch = 0;
+ 
+            // place null character where the number starts
+            // so we know what we've already parsed
+ 
+            srchStr.erase(srchIndex);
+            length = srchStr.length();
+ 
+            /*
+            // shortcut so we dont have to go through an additional while 
+            // loop iteration.
+            if (isalpha(srchStr[srchIndex-1])) {
+                dbText = "alphaSearch = 1";
+                dbprint(1,dbText);
+                alphaSearch = 1;
+                srchIndex--;
+            }
+            */
+        }
+        else if( isalpha(srchStr[srchIndex]) && !digiSearch && !alphaSearch) {
+            alphaSearch = 1;
+        }
+        else if(!isalpha(srchStr[srchIndex]) && !digiSearch && alphaSearch) {
+            
+            // adjust the exponent if none was provided 
+            if (exp == 0) {
+                exp = 1;
+            }
+ 
+            // compare unit string to see if it is a recognized system
+ 
+ 
+            std::string cmpStr = srchStr.substr(srchIndex+1,length-srchIndex-1);
+            cmpIndex = 0;
+ 
+            if ( (unsigned)(cmpIndex = pre_compare(cmpStr,basis)) == 
+                    std::string::npos ) {
+                alphaSearch = 0;
+ 
+                // there are units we did not recognize,
+                // right now we ignore them,
+                // we may want to deal with them differntly in the future
+ 
+                // srchStr.erase(srchIndex+1);
+                // erase only the last character and reprocess the string
+                // because our precompare doesnt take care of this yet.
+                srchStr.erase(srchStr.length()-1);
+                length = srchStr.length();
+                srchIndex = length;
+                
+ 
+                // continue parsing characters
+                continue;
+            }
+ 
+            // the compare function was successful
+            // move the search pointer to one value infront of 
+            // where the units were found.
+            //
+            // cmpIndex tells us how far ahead of the srchIndex the matching
+            // unit was found. so we add srchIndex to get the real index.
+            cmpIndex += srchIndex+1;
+            srchIndex = cmpIndex;
+            std::string newUnitText = srchStr.substr(cmpIndex,length-cmpIndex);
+ 
+            // call the function to create the unit object
+ 
+            // we need pre-compare to return the basis of what it found.
+            // addUnit( newUnit, exp, basis)
+            if (newRpUnit) {
+                 // newRpUnit->addUnit( newUnitText, exp, NULL);
+                 newRpUnit->addUnit( newUnitText, exp, basis);
+            }
+            else {
+                 // newRpUnit= new RpUnits(newUnitText, exp, NULL);
+                 newRpUnit= new RpUnits(newUnitText, exp, basis);
+            }
+ 
+            // sprintf(dbText,"creating unit: %s,%d\n\0", newUnit.c_str(),exp);
+ 
+            // place a null character at the end of the string
+            // so we know what we've parsed so far.
+         
+            srchStr.erase(srchIndex);
+            length = srchStr.length();
+ 
+            // fix our searching flag
+            alphaSearch = 0;
+
+            // shortcut so we dont have to go through an additional while 
+            // loop iteration.
+            // this doesnt work out so well, maybe need to reconsider
+            // if (isdigit(*(search--))) {
+            //    dbprint(1,"digiSearch = 1");
+            //    digiSearch = 1;
+            // }
+        }
+        // else if ( *search == '/' ) {
+        else if( srchStr[srchIndex] == '/' ) {
+            // have to go back to all of the objects created and 
+            // multiply their exponents by -1.
+ 
+            if (newRpUnit) {
+                unit* p = newRpUnit->head;
+                while (p) {
+                    oldExponent = p->getExponent();
+                    newExponent = oldExponent*-1;
+                    p->newExponent(newExponent);
+                    p = p->next;
+                }
+            }
+
+            // place a null character at the end of the string
+            // so we know what we've parsed so far.
+        
+            /*
+            end = (search);
+            *end = '\0';
+            */
+ 
+            // srchStr.erase(srchIndex+1);
+            srchStr.erase(srchIndex);
+            length = srchStr.length();
+
+        }
+        else {
+            continue;
+        }
+
+
+    } // end while loop
+        
+
+    // complete the last iteration
+    if (srchIndex < 0) {
+
+
+        if (digiSearch) {
+            // convert whatever is left
+            exp = atoi(&srchStr[srchIndex+1]);
+           
+            // if we get here, that means units name starts with a digit
+            // normally we wont get here, but if we do, should we place
+            // the unit into the dictionary? i think not since digits are
+            // always considered exponents.
+        }
+        else if (alphaSearch) {
+            // adjust the exponent if none was provided 
+            if (exp == 0) {
+                exp = 1;
+            }
+
+            // compare unit string to see if it is a recognized system
+
+            std::string cmpStr = srchStr.substr(srchIndex+1,length-srchIndex-1);
+            cmpIndex = 0;
+
+            if ( (cmpIndex = pre_compare(cmpStr,basis)) < 0 ) {
+                // no matches in the compare function
+
+                // there are units we did not recognize,
+                // right now we ignore them,
+                // we may want to deal with them differntly in the future
+                // ignoring unit
+
+                // break out of creating the last unit.
+
+                // create a new unit with basis of null to show its a 
+                // fundamental type
+                // newRpUnit = new RpUnits(cmpStr, exp, NULL);
+                newRpUnit = new RpUnits(cmpStr, exp, basis);
+                
+                // put the unit into the dictionary
+                // newRpUnit->insert(cmpStr);
+                //
+                newRpUnit->insert(newRpUnit->getUnitsName());
+                
+                // RpUnits::dict.set(cmpStr,newRpUnit);
+
+            }
+            else {
+
+                // the compare function was successful
+                // move the search pointer to one value infront of 
+                // where the units were found.
+                // adjusting the search pointer to point to the units
+                std::string newUnitText = srchStr.substr(cmpIndex,length-cmpIndex); 
+
+                // call the function to create the unit object
+
+                // we need pre-compare to return the basis of what it found.
+                // addUnit( newUnit, exp, basis)
+                if (newRpUnit) {
+                     // newRpUnit->addUnit( newUnitText, exp, NULL );
+                     newRpUnit->addUnit( newUnitText, exp, basis );
+                }
+                else {
+                     // newRpUnit = new RpUnits(newUnitText, exp, NULL);
+                     newRpUnit = new RpUnits(newUnitText, exp, basis);
+                }
+
+                // creating unit
+                //
+                // putting unit into dictionary
+                newRpUnit->insert(newRpUnit->getUnitsName());
+            }
+
+        }
+    }
+
+    // place the new object into the dictionary
+    
+    // return a copy of the new object to user
+    return newRpUnit;
+}
+
+
+/************************************************************************
+ *                                                                      
+ * add relation rule                                                    
+ *                                                                      
+ ************************************************************************/
+RpUnits * RpUnits::define(  RpUnits* from,
+                            RpUnits* to,
+                            double (*convForwFxnPtr)(double),
+                            double (*convBackFxnPtr)(double))
+{ 
+    RpUnits* conv = new RpUnits(from,to,convForwFxnPtr,convBackFxnPtr,NULL,NULL);
+    
+    return conv; 
+}
+
+RpUnits * RpUnits::define(  RpUnits* from,
+                            RpUnits* to,
+                            void* (*convForwFxnPtr)(void*, void*),
+                            void* convForwData,
+                            void* (*convBackFxnPtr)(void*, void*),
+                            void* convBackData)
+{ 
+    RpUnits* conv = new RpUnits(    from,
+                                    to,
+                                    convForwFxnPtr,
+                                    convForwData,
+                                    convBackFxnPtr,
+                                    convBackData,
+                                    NULL,
+                                    NULL);
+    
+    return conv; 
+}
+
+/************************************************************************
+ *                                                                      
+ * report the units this object represents back to the user             
+ *                                                                      
+ * **********************************************************************/
+std::string RpUnits::getUnits() 
+{
+    // return units; 
+
+    std::stringstream unitText;
+    unit* p = head;
+    
+    while (p) {
+        // unitText << p->getUnits() << p->getExponent();
+        unitText << p->getUnits() ;
+        p = p->next;
+    }
+    
+    return (unitText.str()); 
+}
+
+/************************************************************************
+ *                                                                      
+ * report the units this object represents back to the user             
+ *                                                                      
+ * **********************************************************************/
+std::string RpUnits::getUnitsName() 
+{
+    // return units; 
+
+    std::stringstream unitText;
+    unit* p = head;
+    double exponent;
+    
+    while (p) {
+
+        exponent = p->getExponent();
+
+        if (exponent == 1) {
+            unitText << p->getUnits();
+        }
+        else {
+            unitText << p->getUnits() << p->getExponent();
+        }
+
+        p = p->next;
+    }
+    
+    return (unitText.str()); 
+}
+
+/************************************************************************
+ *                                                                      
+ * report the exponent of the units of this object back to the user
+ *                                                                      
+ * **********************************************************************/
+double RpUnits::getExponent() 
+{ 
+    // return exponent; 
+
+    return head->getExponent();
+
+    return 0; 
+}
+
+/************************************************************************
+ *                                                                      
+ *  report the basis of this object to the user                         
+ *                                                                      
+ * **********************************************************************/
+RpUnits * RpUnits::getBasis() 
+{ 
+    // return basis; 
+
+    // check if head exists? 
+
+    return head->getBasis();
+}
+
+/************************************************************************
+ *                                                                      
+ *  convert the current unit to its basis units
+ *  
+ *  Return Codes
+ *      0) no error (could also mean or no prefix was found)
+ *          in some cases, this means the value is in its basis format
+ *      1) the prefix found does not have a built in factor associated.
+ *                                                                      
+ ************************************************************************/
+double RpUnits::makeBasis(double value, int* result)
+{ 
+
+    RpUnits* basis = getBasis();
+    double retVal = value;
+
+    if (result) {
+        *result = 0;
+    }
+
+    if (basis == NULL) {
+        // this unit is a basis
+        // do nothing
+        
+        if (result) {
+            *result = 1;
+        }
+    }
+    else {
+        retVal = convert(basis,value,result);
+    }
+
+    return retVal;
+}
+
+RpUnits& RpUnits::makeBasis(double* value, int* result)
+{
+    RpUnits* basis = getBasis();
+    double retVal = *value;
+    int convResult = 0;
+
+    if (basis == NULL) {
+        // this unit is a basis
+        // do nothing
+        
+        if (result) {
+            *result = 1;
+        }
+    }
+    else {
+        retVal = convert(basis,retVal,&convResult);
+    }
+
+    if ( (convResult == 1) ) {
+        *value = retVal;
+    }
+
+    if (result) {
+        *result = convResult;
+    }
+
+    
+
+    return *this;
+}
+
+/************************************************************************
+ *                                                                      
+ *  static int makeMetric(RpUnits * basis);                      
+ *  create the metric attachments for the given basis.
+ *  should only be used if this unit is of metric type                  
+ *                                                                      
+ * **********************************************************************/
+//static int RpUnits::makeMetric(RpUnits * basis) {
+int RpUnits::makeMetric(RpUnits * basis) {
+
+    if (!basis) {
+        return 0;
+    }
+
+    std::string basisName = basis->getUnits();
+    std::string name;
+    std::string forw, back;
+    
+    name = "c" + basisName;
+    RpUnits * centi = RpUnits::define(name, basis);
+    RpUnits::define(centi, basis, centi2base, base2centi);
+
+    name = "m" + basisName;
+    RpUnits * milli = RpUnits::define(name, basis);
+    RpUnits::define(milli, basis, milli2base, base2milli);
+
+    name = "u" + basisName;
+    RpUnits * micro = RpUnits::define(name, basis);
+    RpUnits::define(micro, basis, micro2base, base2micro);
+
+    name = "n" + basisName;
+    RpUnits * nano  = RpUnits::define(name, basis);
+    RpUnits::define(nano, basis, nano2base, base2nano);
+    
+    name = "p" + basisName;
+    RpUnits * pico  = RpUnits::define(name, basis);
+    RpUnits::define(pico, basis, pico2base, base2pico);
+
+    name = "f" + basisName;
+    RpUnits * femto = RpUnits::define(name, basis);
+    RpUnits::define(femto, basis, femto2base, base2femto);
+
+    name = "a" + basisName;
+    RpUnits * atto  = RpUnits::define(name, basis);
+    RpUnits::define(atto, basis, atto2base, base2atto);
+
+    name = "k" + basisName;
+    RpUnits * kilo  = RpUnits::define(name, basis);
+    RpUnits::define(kilo, basis, kilo2base, base2kilo);
+
+    name = "M" + basisName;
+    RpUnits * mega  = RpUnits::define(name, basis);
+    RpUnits::define(mega, basis, mega2base, base2mega);
+
+    name = "G" + basisName;
+    RpUnits * giga  = RpUnits::define(name, basis);
+    RpUnits::define(giga, basis, giga2base, base2giga);
+
+    name = "T" + basisName;
+    RpUnits * tera  = RpUnits::define(name, basis);
+    RpUnits::define(tera, basis, tera2base, base2tera);
+
+    name = "P" + basisName;
+    RpUnits * peta  = RpUnits::define(name, basis);
+    RpUnits::define(peta, basis, peta2base, base2peta);
+    
+    // 
+    return (1);
+}
+
+
+std::string RpUnits::convert (   RpUnits* toUnits, 
+                        double val, 
+                        int showUnits, 
+                        int* result )
+{
+    double retVal = convert(toUnits,val,result); 
+    std::stringstream unitText;
+    
+
+    if (showUnits) {
+        unitText << retVal << toUnits->getUnits();
+    }
+    else {
+        unitText << retVal;
+    }
+
+    return (unitText.str()); 
+
+}
+
+// user function to convert a value to the provided RpUnits* toUnits
+// if it exists as a conversion from the basis
+// example
+//      cm.convert(meter,10) 
+//      cm.convert(angstrum,100)
+double RpUnits::convert(RpUnits* toUnit, double val, int* result)
+{
+
+    // currently we convert this object to its basis and look for the
+    // connection ot the toUnit object from the basis.
+
+    double value = val;
+    RpUnits* basis = this->getBasis();
+    RpUnits* fromUnit = this;
+    RpUnits* dictToUnit = NULL;
+    convEntry *p;
+    int my_result = 0;
+
+    // set *result to a default value
+    if (result) {
+        *result = 0;
+    }
+
+    // guard against converting to the units you are converting from...
+    // ie. meters->meters
+    if (this->getUnits() == toUnit->getUnits()) {
+        if (result) {
+            *result = 1;
+        }
+        return val;
+    }
+    
+    // convert unit to the basis
+    // makeBasis(&value);
+    // trying to avoid the recursive way of converting to the basis.
+    // need to rethink this.
+    // 
+    if ( (basis) && (basis->getUnits() != toUnit->getUnits()) ) {
+        value = convert(basis,value,&my_result);
+        if (my_result) {
+            fromUnit = basis;
+        }    
+    }
+
+    // find the toUnit in our dictionary.
+
+    dictToUnit = find(toUnit->getUnits());
+
+    // did we find the unit in the dictionary?
+    if (dictToUnit == NULL) {
+        // toUnit was not found in the dictionary
+        return val;
+    }
+
+    // search through the conversion list to find
+    // the conversion to the toUnit.
+
+    if (basis) {
+        p = basis->convList;
+    }
+    else {
+        p = this->convList;
+    }
+
+    if (p == NULL) {
+        // there are no conversions
+        return val;
+    }
+
+    // loop through our conversion list looking for the correct conversion
+    do {
+        
+        if ( (p->conv->toPtr == dictToUnit) && (p->conv->fromPtr == fromUnit) ) {
+            // we found our conversion
+            // call the function pointer with value
+
+            value = p->conv->convForwFxnPtr(value);
+            if (result) {
+                *result = 1;
+            }
+            break;
+        }
+        
+        if ( (p->conv->toPtr == fromUnit) && (p->conv->fromPtr == dictToUnit) ) {
+            // we found our conversion
+            // call the function pointer with value
+
+            value = p->conv->convBackFxnPtr(value);
+            if (result) {
+                *result = 1;
+            }
+            break;
+        }
+
+        p = p->next;
+
+    } while (p != NULL);
+
+
+    if ( p == NULL) {
+        // we did not find the conversion
+        return val;
+    }
+
+    // we found the conversion.
+    // return the converted value.
+    return value;
+
+}
+
+
+void* RpUnits::convert(RpUnits* toUnit, void* val, int* result)
+{
+
+    // currently we convert this object to its basis and look for the
+    // connection ot the toUnit object from the basis.
+
+    void* value = val;
+    RpUnits* basis = this->getBasis();
+    RpUnits* fromUnit = this;
+    RpUnits* dictToUnit = NULL;
+    convEntry *p;
+    int my_result = 0;
+
+    // set *result to a default value
+    if (result) {
+        *result = 0;
+    }
+
+    // guard against converting to the units you are converting from...
+    // ie. meters->meters
+    if (this->getUnits() == toUnit->getUnits()) {
+        if (result) {
+            *result = 1;
+        }
+        return val;
+    }
+    
+    // convert unit to the basis
+    // makeBasis(&value);
+    // trying to avoid the recursive way of converting to the basis.
+    // need to rethink this.
+    // 
+    if ( (basis) && (basis->getUnits() != toUnit->getUnits()) ) {
+        value = convert(basis,value,&my_result);
+        if (my_result) {
+            fromUnit = basis;
+        }    
+    }
+
+    // find the toUnit in our dictionary.
+
+    dictToUnit = find(toUnit->getUnits());
+
+    // did we find the unit in the dictionary?
+    if (dictToUnit == NULL) {
+        // toUnit was not found in the dictionary
+        return val;
+    }
+
+    // search through the conversion list to find
+    // the conversion to the toUnit.
+
+    if (basis) {
+        p = basis->convList;
+    }
+    else {
+        p = this->convList;
+    }
+
+    if (p == NULL) {
+        // there are no conversions
+        return val;
+    }
+
+    // loop through our conversion list looking for the correct conversion
+    do {
+        
+        if ( (p->conv->toPtr == dictToUnit) && (p->conv->fromPtr == fromUnit) ) {
+            // we found our conversion
+            // call the function pointer with value
+
+            value = p->conv->convForwFxnPtrVoid(p->conv->convForwData,value);
+
+            if (result) {
+                *result = 1;
+            }
+            break;
+        }
+        
+        if ( (p->conv->toPtr == fromUnit) && (p->conv->fromPtr == dictToUnit) ) {
+            // we found our conversion
+            // call the function pointer with value
+
+            value = p->conv->convBackFxnPtrVoid(p->conv->convBackData,value);
+            if (result) {
+                *result = 1;
+            }
+            break;
+        }
+
+        p = p->next;
+
+    } while (p != NULL);
+
+
+    if ( p == NULL) {
+        // we did not find the conversion
+        return val;
+    }
+
+    // we found the conversion.
+    // return the converted value.
+    return value;
+
+}
+
+void RpUnits::addUnit( const std::string& units,
+                       double&  exponent,
+                       RpUnits* basis
+                      )
+{
+    unit* p = NULL;
+
+    // check if the list was created previously. if not, start the list
+    if (head == 0) {
+        head = new unit(units,exponent,basis,NULL);
+        return;
+    }
+
+    // now add a new node at the beginning of the list:
+    p = new unit(units,exponent,basis,head);
+    head->prev = p;
+    head = p;
+
+}
+
+int RpUnits::insert(std::string key)
+{
+    int newRecord = 0;
+    RpUnits* val = this;
+    // dict pointer
+    // RpUnits::dict.set(key,val,&newRecord);
+    RpUnits::dict->set(key,val,&newRecord);
+    // std::cout << "key = :" << key << ":" << std::endl;
+    return newRecord;
+}
+
+
+int RpUnits::pre_compare( std::string& units, RpUnits* basis )
+{
+
+    // compare the incomming units with the previously defined units. 
+    // compareStr will hold a copy of the incomming string. 
+    // first look for the units as they are listed in the incomming variable
+    // next look move searchStr toward the end of the string,
+    // each time the pointer is moved, searchStr should be compared to all of
+    // the previously defined units.
+    // if searchStr is at the end of the string, then searchStr will be moved
+    // back to the beginning of the string.
+    // next it will traverse the string again, changing the case of the char
+    // it points to and the resultant string will be compared again to all 
+    // of the previously defined units.
+
+    int compareSuccess = 0;
+    // std::string::size_type units_len = units.length();
+    // char * retVal = NULL;
+    int retIndex = std::string::npos;
+    // std::string compareStr = units;
+    std::string searchStr = units;
+    std::string dbText = "";
+    
+    // pass 1: look for exact match of units as they came into the function
+    //          move searchStr pointer through string to find match.
+    while ( ! compareSuccess && 
+            (searchStr.length() > 0) ) {
+
+        // std::cout << "units = :" << units << ":" << std::endl;
+        // std::cout << "searchStr = :" << searchStr << ":" << std::endl;
+        
+//         if (!compare(searchStr)) {
+        // dict pointer
+        // if (dict.find(searchStr) == dict.getNullEntry()) {
+        if (dict->find(searchStr) == dict->getNullEntry()) {
+            // the string was not found, 
+            // keep incrementing the pointer
+            // searchStr (pass1)  does not match";
+        }
+        else {
+            // compare was successful, 
+            // searchStr (pass1)  found a match
+            compareSuccess++;
+            break;
+            // is it possible to create the unit here and 
+            // keep looking for units fro mthe provided string?
+        }
+
+        searchStr.erase(0,1);
+
+        if (basis) {
+            if ( (searchStr == basis->getUnits()) &&
+                 (searchStr.length() == basis->getUnits().length()) )
+            {
+                break;
+            }
+        }
+    }
+
+
+    if (compareSuccess == 0) {
+        // refresh our searchStr var.
+        searchStr = units;
+    }
+
+    // pass 2: capitolize the first letter of the search string and compare
+    //          for each letter in the string
+    while ( ! compareSuccess &&
+            (searchStr.length() > 0) ) {
+
+        if (islower((int)(searchStr[0]))) {
+            searchStr[0] = (char) toupper((int)(searchStr[0]));
+        }
+
+//        if (!compare(searchStr)) {
+        // dict pointer
+        // if (dict.find(searchStr) == dict.getNullEntry()) {
+        if (dict->find(searchStr) == dict->getNullEntry()) {
+            // the string was not found, 
+            // keep incrementing the pointer
+            // searchStr (pass2)  does not match
+        }
+        else {
+            // compare was successful, 
+            // searchStr (pass2)  found a match
+            compareSuccess++;
+            break;
+        }
+        searchStr.erase(0,1);
+
+        // check to see if we are at the basis.
+        if (basis) {
+            if ( (searchStr == basis->getUnits()) &&
+                 (searchStr.length() == basis->getUnits().length()) )
+            {
+                break;
+            }
+            
+        }
+
+    }
+
+
+
+    // if we found a match, find the first occurance of the string which
+    // was used to get the match, in our original units string.
+    // this gets dicey for capitolizations.
+    if ( compareSuccess ) {
+        // need to think about if we want to search from the start
+        // or the end of the string (find or rfind)
+        // i think its the start because in this fxn (above)
+        // we start at the beginning of the string and work
+        // our way to the end. so if there is a second match at the
+        // end, we would have only seen the first match.
+        retIndex = units.find(searchStr);
+    }
+
+    return retIndex;
+
+    /*
+    if (retIndex) {
+        // if we found a match return a 
+        // pointer to where the matching units 
+        // string can be found.
+        dbText = "pre_compare returning an index";
+        dbprint(1, dbText);
+        return retIndex;
+    }
+    else {
+        // if there was no match, return a negative value.
+        dbText = "pre_compare returning -1";
+        dbprint(1, dbText);
+        return -1;
+    }
+    */
+}
+
+
+void RpUnits::connectConversion(RpUnits* myRpUnit) 
+{
+
+    /*
+    int index = 0;
+
+    while   ( (myRpUnit->staticConvArr[index] != NULL) 
+         &&   (index < myRpUnit->numBuckets) ){
+
+        index++;
+    }
+
+    if      ( (myRpUnit->staticConvArr[index] == NULL)
+        &&    (index < myRpUnit->numBuckets) ) {
+            
+        myRpUnit->staticConvArr[index] = this->conv;
+    }
+    */
+
+    convEntry* p = myRpUnit->convList;
+
+    if (p == NULL) {
+        myRpUnit->convList = new convEntry (this->conv,NULL,NULL);
+    }
+    else {
+        while (p->next != NULL) {
+            p = p->next;
+        }
+
+        p->next = new convEntry (this->conv,p,NULL);
+    }
+
+}
+
+
+// -------------------------------------------------------------------- //
+
Index: /trunk/src/core/RpUnitsStd.cc
===================================================================
--- /trunk/src/core/RpUnitsStd.cc	(revision 20)
+++ /trunk/src/core/RpUnitsStd.cc	(revision 20)
@@ -0,0 +1,172 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************
+ * METRIC CONVERSIONS
+ ****************************************/
+
+double centi2base (double centi) 
+{
+   return centi*1e-2;    
+}
+
+double milli2base (double milli)
+{
+    return milli*1e-3;
+}
+
+double micro2base (double micro)
+{
+    return micro*1e-6;
+}
+
+double nano2base (double nano)
+{
+    return nano*1e-9;
+}
+
+double pico2base (double pico)
+{
+    return pico*1e-12;
+}
+
+double femto2base (double femto)
+{
+    return femto*1e-15;
+}
+
+double atto2base (double atto)
+{
+    return atto*1e-18;
+}
+
+double kilo2base (double kilo)
+{
+    return kilo*1e3;
+}
+
+double mega2base (double mega)
+{
+    return mega*1e6;
+}
+
+double giga2base (double giga)
+{
+    return giga*1e9;
+}
+
+double tera2base (double tera)
+{
+    return tera*1e12;
+}
+
+double peta2base (double peta)
+{
+    return peta*1e15;
+}
+
+double base2centi (double base) 
+{
+    return base*1e2;    
+}
+
+double base2milli (double base)
+{
+    return base*1e3;
+}
+
+double base2micro (double base)
+{
+    return base*1e6;
+}
+
+double base2nano (double base)
+{
+    return base*1e9;
+}
+
+double base2pico (double base)
+{
+    return base*1e12;
+}
+
+double base2femto (double base)
+{
+    return base*1e15;
+}
+
+double base2atto (double base)
+{
+    return base*1e18;
+}
+
+double base2kilo (double base)
+{
+    return base*1e-3;
+}
+
+double base2mega (double base)
+{
+    return base*1e-6;
+}
+
+double base2giga (double base)
+{
+    return base*1e-9;
+}
+
+double base2tera (double base)
+{
+    return base*1e-12;
+}
+
+double base2peta (double base)
+{
+    return base*1e-15;
+}
+
+
+
+/****************************************
+ * METRIC TO NON-METRIC CONVERSIONS
+ ****************************************/
+
+double angstrom2meter (double angstrom)
+{
+        return angstrom*1.0e-10;
+}
+
+double meter2angstrom (double meters)
+{
+        return meters*1.0e10;
+}
+
+/****************************************
+ * TEMPERATURE CONVERSIONS
+ ****************************************/
+
+double fahrenheit2centigrade (double F)
+{
+        return ((F-32.0)/(9.0/5.0));
+}
+
+double centigrade2fahrenheit (double C)
+{
+        return ((C*(9.0/5.0))+32.0);
+}
+
+double centigrade2kelvin (double C)
+{
+        return (C+273.15);
+}
+
+double kelvin2centigrade (double K)
+{
+        return (K-273.15);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
Index: /trunk/src/fortran/RpUnits_fortran.c
===================================================================
--- /trunk/src/fortran/RpUnits_fortran.c	(revision 20)
+++ /trunk/src/fortran/RpUnits_fortran.c	(revision 20)
@@ -0,0 +1,323 @@
+// #include "../include/RpUnitsCInterface.h"
+// #include "../include/RpDictCFInterface.h"
+// #include <stdio.h>
+
+#include "../include/RpUnits.h"
+#include "../include/RpDict.h"
+#include "string.h"
+
+#ifdef COMPNAME_ADD1UNDERSCORE
+#   define rp_define_unit       rp_define_unit_
+#   define rp_find              rp_find_
+#   define rp_make_metric       rp_make_metric_
+#   define rp_get_units         rp_get_units_
+#   define rp_get_units_name    rp_get_units_name_
+#   define rp_get_exponent      rp_get_exponent_
+#   define rp_get_basis         rp_get_basis_
+#elif defined(COMPNAME_ADD2UNDERSCORE)
+#   define rp_define_unit       rp_define_unit__
+#   define rp_find              rp_find__
+#   define rp_make_metric       rp_make_metric__
+#   define rp_get_units         rp_get_units__
+#   define rp_get_units_name    rp_get_units_name__
+#   define rp_get_exponent      rp_get_exponent__
+#   define rp_get_basis         rp_get_basis__
+#elif defined(COMPNAME_NOCHANGE)
+#   define rp_define_unit       rp_define_unit
+#   define rp_find              rp_find
+#   define rp_make_metric       rp_make_metric
+#   define rp_get_units         rp_get_units
+#   define rp_get_units_name    rp_get_units_name
+#   define rp_get_exponent      rp_get_exponent
+#   define rp_get_basis         rp_get_basis
+#elif defined(COMPNAME_UPPERCASE)
+#   define rp_define_unit       RP_DEFINE_UNIT
+#   define rp_find              RP_FIND
+#   define rp_make_metric       RP_MAKE_METRIC
+#   define rp_get_units         RP_GET_UNITS
+#   define rp_get_units_name    RP_GET_UNITS_NAME 
+#   define rp_get_exponent      RP_GET_EXPONENT
+#   define rp_get_basis         RP_GET_BASIS
+#endif
+
+extern "C"
+int rp_define_unit(char* unitName, int* basisName, int unitName_len);
+
+extern "C"
+int rp_find(char* searchName, int searchName_len);
+
+extern "C"
+int rp_make_metric(int* basis);
+
+extern "C"
+void rp_get_units(int* unitRefVal, char* retText, int retText_len);
+
+extern "C"
+void rp_get_units_name(int* unitRefVal, char* retText, int retText_len);
+
+extern "C"
+double rp_get_exponent(int* unitRefVal);
+
+extern "C"
+int rp_get_basis(int* unitRefVal);
+
+
+
+
+
+
+
+
+char* null_terminate(char* inStr, int len);
+int storeObject(std::string objectName);
+RpUnits* getObject(int objKey);
+
+
+
+
+#define DICT_TEMPLATE <int,std::string>
+// RpDict<int,std::string>fortObjDict;
+RpDict DICT_TEMPLATE fortObjDict;
+
+int rp_define_unit( char* unitName, 
+                    int* basisName, 
+                    int unitName_len    ) {
+
+    int retVal = -1;
+    RpUnits* newUnit = NULL;
+    RpUnits* basis = NULL;
+    std::string basisStrName = "";
+    std::string newUnitName = "";
+    char* inText = NULL;
+
+    inText = null_terminate(unitName,unitName_len);
+
+    if (basisName && *basisName) {
+        basisStrName = fortObjDict.find(*basisName);
+
+        if (basisStrName != "") {
+            basis = RpUnits::find(basisStrName);
+        }
+    }
+
+    // newUnit = RpUnits::define(unitName, basis);
+    newUnit = RpUnits::define(inText, basis);
+    
+    if (newUnit) {
+        retVal = storeObject(newUnit->getUnitsName());
+    }
+
+    if (inText) {
+        free(inText);
+    }
+
+    return retVal;
+}
+
+
+int rp_find(char* searchName, int searchName_len)
+{
+
+    int retVal = -1;
+    char* inText = NULL;
+
+    inText = null_terminate(searchName,searchName_len);
+
+    // RpUnits* searchUnit = RpUnits::find(searchName);
+    RpUnits* searchUnit = RpUnits::find(inText);
+
+    if (searchUnit) {
+        retVal = storeObject(searchUnit->getUnitsName());
+    }
+
+    if (inText) {
+        free(inText);
+    }
+
+    return retVal;
+}
+
+int rp_make_metric(int* basis)
+{
+    int retVal = -1;
+    RpUnits* newBasis = NULL;
+
+    if (basis && *basis) {
+        newBasis = getObject(*basis);
+
+        if (newBasis) {
+            retVal = RpUnits::makeMetric(newBasis);
+        }
+    }
+
+    return retVal;
+}
+
+void rp_get_units(int* unitRefVal, char* retText, int retText_len)
+{
+    int length_in = 0;
+    int length_out = 0;
+    int i = 0;
+    RpUnits* unitObj = NULL;
+    std::string unitNameText = "";
+
+    if (unitRefVal && *unitRefVal) {
+        unitObj = getObject(*unitRefVal);
+        if (unitObj) {
+            unitNameText = unitObj->getUnits();
+
+            length_in = unitNameText.length();
+            length_out = retText_len;
+
+            strncpy(retText, unitNameText.c_str(), length_out);
+
+            // fortran-ify the string
+            if (length_in < length_out) {
+                for (i = length_in; i < length_out; i++) {
+                    retText[i] = ' ';
+                }
+            }
+                
+        }
+    }
+}
+
+void rp_get_units_name(int* unitRefVal, char* retText, int retText_len)
+{
+    int length_in = 0;
+    int length_out = 0;
+    int i = 0;
+    RpUnits* unitObj = NULL;
+    std::string unitNameText = "";
+
+    if (unitRefVal && *unitRefVal) {
+        unitObj = getObject(*unitRefVal);
+        if (unitObj) {
+            unitNameText = unitObj->getUnitsName();
+
+            length_in = unitNameText.length();
+            length_out = retText_len;
+
+            strncpy(retText, unitNameText.c_str(), length_out);
+
+            // fortran-ify the string
+            if (length_in < length_out) {
+                for (i = length_in; i < length_out; i++) {
+                    retText[i] = ' ';
+                }
+            }
+                
+        }
+    }
+
+}
+
+double rp_get_exponent(int* unitRefVal)
+{
+    RpUnits* unitObj = NULL;
+    double retVal = 0;
+
+    if (unitRefVal && *unitRefVal) {
+        unitObj = getObject(*unitRefVal);
+        if (unitObj) {
+            retVal = unitObj->getExponent();
+        }
+    }
+
+    return retVal;
+}
+
+int rp_get_basis(int* unitRefVal)
+{
+    RpUnits* unitObj = NULL;
+    RpUnits* basisObj = NULL;
+    int retVal = -1;
+
+    if (unitRefVal && *unitRefVal) {
+        unitObj = getObject(*unitRefVal);
+
+        if (unitObj) {
+            basisObj = unitObj->getBasis();
+            
+            if (basisObj) {
+                retVal = storeObject(basisObj->getUnitsName());
+            }
+        }
+    }
+
+    return retVal;
+}
+
+
+
+
+
+
+
+
+
+
+
+int storeObject(std::string objectName) {
+
+    int retVal = -1;
+    int dictNextKey = fortObjDict.size() + 1;
+    int newEntry = 0;
+
+    if (objectName != "") {
+        // dictionary returns a reference to the inserted value
+        // no error checking to make sure it was successful in entering
+        // the new entry.
+        fortObjDict.set(dictNextKey,objectName, &newEntry); 
+    }
+    
+    retVal = dictNextKey;
+    return retVal;
+}
+
+RpUnits* getObject(int objKey) {
+
+    std::string basisName = *(fortObjDict.find(objKey).getValue());
+
+    if (basisName == *(fortObjDict.getNullEntry().getValue())) {
+        // basisName = "";
+        return NULL;
+    }
+
+   return RpUnits::find(basisName);
+
+}
+
+/* fix buffer overflow possibility*/
+char* null_terminate(char* inStr, int len)
+{
+    int retVal = 0;
+    int origLen = len;
+    char* newStr = NULL;
+
+    if (inStr) {
+
+        while ((len > 0) && (isspace(*(inStr+len-1)))) {
+            // dont strip off newlines
+            if ( (*(inStr+len-1) == '\f')
+              || (*(inStr+len-1) == '\n')
+              || (*(inStr+len-1) == '\r')
+              || (*(inStr+len-1) == '\t')
+              || (*(inStr+len-1) == '\v') )
+            {
+                break;
+            }
+            len--;
+        }
+
+        newStr = (char*) calloc(len+1,(sizeof(char)));
+        strncpy(newStr,inStr,len);
+        *(newStr+len) = '\0';
+
+        retVal++;
+    }
+
+    // return retVal;
+
+    return newStr;
+}
Index: /trunk/src/fortran/rappture_fortran.c
===================================================================
--- /trunk/src/fortran/rappture_fortran.c	(revision 20)
+++ /trunk/src/fortran/rappture_fortran.c	(revision 20)
@@ -0,0 +1,1390 @@
+#include "../include/rappture_interface.h"
+#include "../include/RpDict.h"
+#include <string.h>
+
+/*
+// rappture-fortran api
+*/
+
+#ifdef COMPNAME_ADD1UNDERSCORE
+#   define rp_init                 rp_init_
+#   define rp_lib                  rp_lib_
+#   define rp_lib_element_comp     rp_lib_element_comp_
+#   define rp_lib_element_id       rp_lib_element_id_
+#   define rp_lib_element_type     rp_lib_element_type_
+#   define rp_lib_element_str      rp_lib_element_str_
+#   define rp_lib_element_obj      rp_lib_element_obj_
+#   define rp_lib_child_num        rp_lib_child_num_
+#   define rp_lib_child_comp       rp_lib_child_comp_
+#   define rp_lib_child_id         rp_lib_child_id_
+#   define rp_lib_child_type       rp_lib_child_type_
+#   define rp_lib_child_str        rp_lib_child_str_
+#   define rp_lib_child_obj        rp_lib_child_obj_
+#   define rp_lib_get              rp_lib_get_
+#   define rp_lib_get_double       rp_lib_get_double_
+#   define rp_lib_put_str          rp_lib_put_str_
+#   define rp_lib_put_id_str       rp_lib_put_id_str_
+#   define rp_lib_put_obj          rp_lib_put_obj_
+#   define rp_lib_put_id_obj       rp_lib_put_id_obj_
+#   define rp_lib_remove           rp_lib_remove_
+#   define rp_lib_xml_len          rp_lib_xml_len_
+#   define rp_lib_write_xml        rp_lib_write_xml_
+#   define rp_lib_xml              rp_lib_xml_
+#   define rp_quit                 rp_quit_
+#elif defined(COMPNAME_ADD2UNDERSCORE)
+#   define rp_init                 rp_init__
+#   define rp_lib                  rp_lib__
+#   define rp_lib_element_comp     rp_lib_element_comp__
+#   define rp_lib_element_id       rp_lib_element_id__
+#   define rp_lib_element_type     rp_lib_element_type__
+#   define rp_lib_element_str      rp_lib_element_str__
+#   define rp_lib_element_obj      rp_lib_element_obj__
+#   define rp_lib_child_num        rp_lib_child_num__
+#   define rp_lib_child_comp       rp_lib_child_comp__
+#   define rp_lib_child_id         rp_lib_child_id__
+#   define rp_lib_child_type       rp_lib_child_type__
+#   define rp_lib_child_str        rp_lib_child_str__
+#   define rp_lib_child_obj        rp_lib_child_obj__
+#   define rp_lib_get              rp_lib_get__
+#   define rp_lib_get_double       rp_lib_get_double__
+#   define rp_lib_put_str          rp_lib_put_str__
+#   define rp_lib_put_id_str       rp_lib_put_id_str__
+#   define rp_lib_put_obj          rp_lib_put_obj__
+#   define rp_lib_put_id_obj       rp_lib_put_id_obj__
+#   define rp_lib_remove           rp_lib_remove__
+#   define rp_lib_xml_len          rp_lib_xml_len__
+#   define rp_lib_write_xml        rp_lib_write_xml__
+#   define rp_lib_xml              rp_lib_xml__
+#   define rp_quit                 rp_quit__
+#elif defined(COMPNAME_NOCHANGE)
+#   define rp_init                 rp_init
+#   define rp_lib                  rp_lib
+#   define rp_lib_element_comp     rp_lib_element_comp
+#   define rp_lib_element_id       rp_lib_element_id
+#   define rp_lib_element_type     rp_lib_element_type
+#   define rp_lib_element_str      rp_lib_element_str
+#   define rp_lib_element_obj      rp_lib_element_obj
+#   define rp_lib_child_num        rp_lib_child_num
+#   define rp_lib_child_comp       rp_lib_child_comp
+#   define rp_lib_child_id         rp_lib_child_id
+#   define rp_lib_child_type       rp_lib_child_type
+#   define rp_lib_child_str        rp_lib_child_str
+#   define rp_lib_child_obj        rp_lib_child_obj
+#   define rp_lib_get              rp_lib_get
+#   define rp_lib_get_double       rp_lib_get_double
+#   define rp_lib_put_str          rp_lib_put_str
+#   define rp_lib_put_id_str       rp_lib_put_id_str
+#   define rp_lib_put_obj          rp_lib_put_obj
+#   define rp_lib_put_id_obj       rp_lib_put_id_obj
+#   define rp_lib_remove           rp_lib_remove
+#   define rp_lib_xml_len          rp_lib_xml_len
+#   define rp_lib_write_xml        rp_lib_write_xml
+#   define rp_lib_xml              rp_lib_xml
+#   define rp_quit                 rp_quit
+#elif defined(COMPNAME_UPPERCASE)
+#   define rp_init                 RP_INIT
+#   define rp_lib                  RP_LIB
+#   define rp_lib_element_comp     RP_LIB_ELEMENT_COMP
+#   define rp_lib_element_id       RP_LIB_ELEMENT_ID
+#   define rp_lib_element_type     RP_LIB_ELEMENT_TYPE
+#   define rp_lib_element_str      RP_LIB_ELEMENT_STR 
+#   define rp_lib_element_obj      RP_LIB_ELEMENT_OBJ
+#   define rp_lib_child_num        RP_LIB_CHILD_NUM
+#   define rp_lib_child_comp       RP_LIB_CHILD_COMP
+#   define rp_lib_child_id         RP_LIB_CHILD_ID
+#   define rp_lib_child_type       RP_LIB_CHILD_TYPE
+#   define rp_lib_child_str        RP_LIB_CHILD_STR
+#   define rp_lib_child_obj        RP_LIB_CHILD_OBJ
+#   define rp_lib_get              RP_LIB_GET
+#   define rp_lib_get_double       RP_LIB_GET_DOUBLE
+#   define rp_lib_put_str          RP_LIB_PUT_STR
+#   define rp_lib_put_id_str       RP_LIB_PUT_ID_STR
+#   define rp_lib_put_obj          RP_LIB_PUT_OBJ
+#   define rp_lib_put_id_obj       RP_LIB_PUT_ID_OBJ
+#   define rp_lib_remove           RP_LIB_REMOVE
+#   define rp_lib_xml_len          RP_LIB_XML_LEN
+#   define rp_lib_write_xml        RP_LIB_WRITE_XML
+#   define rp_lib_xml              RP_LIB_XML
+#   define rp_quit                 RP_QUIT
+#endif
+
+
+extern "C"
+void rp_init();
+
+extern "C"
+int rp_lib(const char* filePath, int filePath_len);
+
+extern "C"
+void rp_lib_element_comp( int* handle, 
+                            char* path,
+                            char* retText,
+                            int path_len,
+                            int retText_len );
+
+extern "C"
+void rp_lib_element_id(   int* handle, 
+                            char* path,
+                            char* retText,
+                            int path_len,
+                            int retText_len );
+
+extern "C"
+void rp_lib_element_type( int* handle,
+                            char* path,
+                            char* retText,
+                            int path_len,
+                            int retText_len );
+
+extern "C"
+void rp_lib_element_str(  int* handle, 
+                            char* path, 
+                            char* flavor,
+                            char* retText,
+                            int path_len,
+                            int flavor_len,
+                            int retText_len );
+
+extern "C"
+int rp_lib_element_obj(   int* handle, 
+                            char* path,
+                            int path_len );
+
+extern "C"
+int rp_lib_child_num(    int* handle, 
+                            char* path, 
+                            int path_len);
+
+extern "C"
+int rp_lib_child_comp(   int* handle,    /* integer handle of library */
+                            char* path,     /* DOM path of requested object */
+                            char* type,     /* specific name of element */
+                            int* childNum,  /* child number for iteration */
+                            char* retText,  /* buffer to store return text */
+                            int path_len,   /* length of path */
+                            int type_len,   /* length of type */
+                            int retText_len /* length of return text buffer */
+                       );
+
+extern "C"
+int rp_lib_child_id(     int* handle,    /* integer handle of library */
+                            char* path,     /* DOM path of requested object */
+                            char* type,     /* specific name of element */
+                            int* childNum,  /* child number for iteration */
+                            char* retText,  /* buffer to store return text */
+                            int path_len,   /* length of path */
+                            int type_len,   /* length of type */
+                            int retText_len /* length of return text buffer */
+                       );
+
+extern "C"
+int rp_lib_child_type(   int* handle,    /* integer handle of library */
+                            char* path,     /* DOM path of requested object */
+                            char* type,     /* specific name of element */
+                            int* childNum,  /* child number for iteration */
+                            char* retText,  /* buffer to store return text */
+                            int path_len,   /* length of path */
+                            int type_len,   /* length of type */
+                            int retText_len /* length of return text buffer */
+                       );
+
+extern "C"
+int rp_lib_child_str(    int* handle,    /* integer handle of library */
+                            char* path,     /* DOM path of requested object */
+                            char* flavor,   /* information you want returned*/
+                            char* type,     /* specific name of element */
+                            int* childNum,  /* child number for iteration */
+                            char* retText,  /* buffer to store return text */
+                            int path_len,   /* length of path */
+                            int flavor_len, /* length of flavor */
+                            int type_len,   /* length of type */
+                            int retText_len /* length of return text buffer */
+                       );
+
+extern "C"
+int rp_lib_child_obj(    int* handle, 
+                            char* path, 
+                            char* type, 
+                            int path_len,
+                            int type_len
+                          );
+
+extern "C"
+void rp_lib_get(          int* handle, 
+                            char* path,
+                            char* retText,
+                            int path_len,
+                            int retText_len );
+
+extern "C"
+double rp_lib_get_double( int* handle, 
+                            char* path,
+                            int path_len);
+
+extern "C"
+void rp_lib_put_str(     int* handle, 
+                            char* path, 
+                            char* value, 
+                            int* append,
+                            int path_len,
+                            int value_len ); 
+
+extern "C"
+void rp_lib_put_id_str(  int* handle, 
+                            char* path, 
+                            char* value, 
+                            char* id, 
+                            int* append,
+                            int path_len,
+                            int value_len,
+                            int id_len ); 
+
+extern "C"
+void rp_lib_put_obj(     int* handle, 
+                            char* path, 
+                            int* valHandle, 
+                            int* append,
+                            int path_len ); 
+
+extern "C"
+void rp_lib_put_id_obj(  int* handle, 
+                            char* path, 
+                            int* valHandle, 
+                            char* id, 
+                            int* append,
+                            int path_len,
+                            int id_len ); 
+
+extern "C"
+int rp_lib_remove(       int* handle, 
+                            char* path, 
+                            int path_len);
+
+extern "C"
+int rp_lib_xml_len(      int* handle);
+
+extern "C"
+void rp_lib_xml(         int* handle, 
+                            char* retText, 
+                            int retText_len);
+
+extern "C"
+int rp_lib_write_xml(     int* handle, 
+                            char* outFile, 
+                            int outFile_len);
+extern "C"
+void rp_quit();
+
+
+/**********************************************************/
+
+/**********************************************************/
+
+// private member functions
+int storeNode(PyObject* node);
+int objType( char* flavor);
+
+int storeObject(PyObject* objectName);
+PyObject* getObject(int objKey);
+char* null_terminate(char* inStr, int len);
+
+// global vars
+// dictionary to hold the python objects that 
+// cannot be sent to fortran
+
+#define DICT_TEMPLATE <int,PyObject*>
+RpDict DICT_TEMPLATE fortObjDict;
+int rapptureStarted = 0;
+
+void rp_init() {
+    //
+    PyObject* rpClass = NULL;
+    int retVal = 0;
+    
+    // initialize the interpreter
+    Py_Initialize();
+    rpClass = importRappture();
+
+    if (rpClass) {
+        // store the handle in the dictionary
+        retVal = storeObject(rpClass);
+        rapptureStarted = 1;
+    }
+}
+
+int rp_lib(const char* filePath, int filePath_len) 
+{
+    PyObject* lib = NULL;
+    PyObject* rpClass = NULL;
+    int handle = -1;
+    char* inFilePath = NULL;
+
+    if (!rapptureStarted) {
+        rp_init();
+    }
+
+
+    inFilePath = null_terminate((char*)filePath, filePath_len);
+    
+    // error checking to make sure inText is valid???
+    
+    // grab the rappture class from the dictionary
+    rpClass = getObject(0);
+
+    if (rpClass) {
+        // create a RapptureIO object and store in dictionary
+        lib = createRapptureObj(rpClass, inFilePath);
+
+        if (lib) {
+            handle = storeObject(lib);
+        }
+    }
+
+    if (inFilePath) {
+        free(inFilePath);
+        inFilePath = NULL;
+    }
+
+    return handle;
+}
+
+int rp_lib_element_obj(int* handle,     /* integer handle of library */
+                          char* path,     /* null terminated path */
+                          int path_len
+                        )
+{
+    int newObjHandle = -1;
+
+    const char* flavor = "object";
+    char* inPath = NULL;
+
+    PyObject* lib = NULL;
+    PyObject* retObj = NULL;
+
+    inPath = null_terminate(path,path_len);
+
+    // error checking to make sure inText is valid???
+
+    if (fortObjDict.size() > 0) {
+        if ((handle) && (*handle != 0)) {
+            lib = getObject(*handle);
+            if (lib) {
+                retObj = (PyObject*) rpElement(lib, inPath, flavor);
+                
+                if (retObj) {
+
+                    newObjHandle = storeObject(retObj);
+                    // Py_DECREF(retObj);
+                }
+            }
+        }
+    }
+
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+    return newObjHandle;
+}
+
+void rp_lib_element_comp( int* handle, /* integer handle of library */
+                            char* path,      /* null terminated path */
+                            char* retText,   /* return buffer for fortran*/
+                            int path_len,
+                            int retText_len /* length of return text buffer */
+                          )
+{
+    char* inPath = NULL;
+
+    inPath = null_terminate(path,path_len);
+    if (path_len) {
+        path_len = strlen(inPath) + 1;
+    }
+    else {
+        path_len = 0;
+    }
+
+    // error checking to make sure inText is valid???
+
+    rp_lib_element_str(handle,inPath,"component",retText,path_len,10,retText_len);
+    
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+}
+
+void rp_lib_element_id(   int* handle, /* integer handle of library */
+                            char* path,      /* null terminated path */
+                            char* retText,   /* return buffer for fortran*/
+                            int path_len,
+                            int retText_len /* length of return text buffer */
+                        ) 
+{
+    char* inPath = NULL;
+    inPath = null_terminate(path,path_len);
+    if (inPath) {
+        path_len = strlen(inPath) + 1;
+    }
+    else {
+        path_len = 0;
+    }
+
+    rp_lib_element_str(handle,inPath,"id",retText,path_len,3,retText_len);
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+
+}
+
+void rp_lib_element_type( int* handle, /* integer handle of library */
+                            char* path,      /* null terminated path */
+                            char* retText,   /* return buffer for fortran*/
+                            int path_len,
+                            int retText_len /* length of return text buffer */
+                          )
+{
+    char* inPath = NULL;
+    inPath = null_terminate(path,path_len);
+    if (inPath) {
+        path_len = strlen(inPath) + 1;
+    }
+    else {
+        path_len = 0;
+    }
+    rp_lib_element_str(handle,path,"type",retText,path_len,5,retText_len);
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+
+}
+
+void rp_lib_element_str(  int* handle, /* integer handle of library */
+                            char* path,      /* null terminated path */
+                            char* flavor,    /* null terminated flavor */
+                            char* retText,   /* return buffer for fortran*/
+                            int path_len,
+                            int flavor_len,
+                            int retText_len /* length of return text buffer */
+                        )
+{
+    int length_in = 0;
+    int length_out = 0;
+    int i = 0;
+    const char* xmlText = NULL;
+
+    PyObject* lib = NULL;
+    
+    char* retObj = NULL;
+    
+    char* inPath = NULL;
+    char* inFlavor = NULL;
+
+    inPath = null_terminate(path,path_len);
+    inFlavor = null_terminate(flavor,flavor_len);
+
+    if (rapptureStarted) {
+        if ((handle) && (*handle != 0)) {
+            lib = getObject(*handle);
+
+            if (lib) {
+                if(objType(inFlavor) == 1) {
+
+                    retObj = (char*) rpElement(lib, inPath, inFlavor);
+                    if (retObj) {
+                        xmlText = retObj;
+                    
+                        length_in = strlen(xmlText);
+                        length_out = retText_len;
+
+                        strncpy(retText, xmlText, length_out);
+
+                        // fortran-ify the string
+                        if (length_in < length_out) {
+                              for (i = length_in; i < length_out; i++) {
+                                  retText[i] = ' ';
+                              }
+                        }
+                        *(retText+length_out-1) = ' ';
+
+                    }
+                    else {
+                        
+                    }
+                }
+
+            }
+        }
+    }
+    
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+    if (inFlavor) {
+        free(inFlavor);
+        inFlavor = NULL;
+    }
+
+}
+
+int rp_lib_child_num( int* handle, 
+                         char* path, 
+                         int path_len
+                       )
+{
+    int numChildren = 0;
+
+    PyObject* lib = NULL;
+    PyObject* list = NULL;
+    char* inPath = NULL;
+
+    inPath = null_terminate(path,path_len);
+    
+    if (rapptureStarted) {
+        if ((handle) && (*handle != 0)) {
+            lib = getObject(*handle);
+
+            if (lib) {
+                list = rpChildren_f(lib, inPath, "type");
+                if (list) {
+                    numChildren = PyList_Size(list);
+                    Py_DECREF(list);
+                }
+                else {
+                    
+                }
+            }
+        }
+    }
+
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+    return numChildren;
+
+}
+
+
+int rp_lib_child_comp (   int* handle,    /* integer handle of library */
+                            char* path,     /* DOM path of requested object */
+                            char* type,     /* specific name of element */
+                            int* childNum,  /* child number for iteration */
+                            char* retText,  /* buffer to store return text */
+                            int path_len,   /* length of path */
+                            int type_len,   /* length of type */
+                            int retText_len /* length of return text buffer */
+                       )
+{
+    int retVal = 0;
+
+    char* inPath = NULL;
+    char* inType = NULL;
+
+    inPath = null_terminate(path,path_len);
+    inType = null_terminate(type,type_len);
+
+    if (inPath) {
+        path_len = strlen(inPath) + 1;
+    }
+    else {
+        path_len = 0;
+    }
+
+    if (inType) {
+        type_len = strlen(inType) + 1;
+    }
+    else {
+        type_len = 0;
+    }
+
+    retVal = rp_lib_child_str( handle,
+                                 inPath,
+                                 "component",
+                                 inType,
+                                 childNum,
+                                 retText,
+                                 path_len,
+                                 10,
+                                 type_len,
+                                 retText_len
+                               );
+
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+    if (inType) {
+        free(inType);
+        inType = NULL;
+    }
+
+    return retVal;
+}
+
+int rp_lib_child_id(   int* handle,    /* integer handle of library */
+                          char* path,     /* DOM path of requested object */
+                          char* type,     /* specific name of element */
+                          int* childNum,  /* child number for iteration */
+                          char* retText,  /* buffer to store return text */
+                          int path_len,   /* length of path */
+                          int type_len,   /* length of type */
+                          int retText_len /* length of return text buffer */
+                       )
+{
+    int retVal = 0;
+    char* inPath = NULL;
+    char* inType = NULL;
+
+    inPath = null_terminate(path,path_len);
+    inType = null_terminate(type,type_len);
+
+    if (inPath) {
+        path_len = strlen(inPath) + 1;
+    }
+    else {
+        path_len = 0;
+    }
+
+    if (inType) {
+        type_len = strlen(inType) + 1;
+    }
+    else {
+        type_len = 0;
+    }
+
+    retVal = rp_lib_child_str( handle,
+                                 inPath,
+                                 "id",
+                                 inType,
+                                 childNum,
+                                 retText,
+                                 path_len,
+                                 3,
+                                 type_len,
+                                 retText_len
+                               );
+
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+    if (inType) {
+        free(inType);
+        inType = NULL;
+    }
+
+    return retVal;
+}
+
+int rp_lib_child_type (   int* handle,    /* integer handle of library */
+                            char* path,     /* DOM path of requested object */
+                            char* type,     /* specific name of element */
+                            int* childNum,  /* child number for iteration */
+                            char* retText,  /* buffer to store return text */
+                            int path_len,   /* length of path */
+                            int type_len,   /* length of type */
+                            int retText_len /* length of return text buffer */
+                       )
+{
+    int retVal = 0;
+    char* inPath = NULL;
+    char* inType = NULL;
+
+    inPath = null_terminate(path,path_len);
+    inType = null_terminate(type,type_len);
+
+    if (inPath) {
+        path_len = strlen(inPath) + 1;
+    }
+    else {
+        path_len = 0;
+    }
+
+    if (inType) {
+        type_len = strlen(inType) + 1;
+    }
+    else {
+        type_len = 0;
+    }
+
+    retVal = rp_lib_child_str( handle,
+                                 inPath,
+                                 "type",
+                                 inType,
+                                 childNum,
+                                 retText,
+                                 path_len,
+                                 5,
+                                 type_len,
+                                 retText_len
+                               );
+
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+    if (inType) {
+        free(inType);
+        inType = NULL;
+    }
+
+    return retVal;
+}
+
+int rp_lib_child_str (    int* handle,    /* integer handle of library */
+                            char* path,     /* DOM path of requested object */
+                            char* flavor,   /* information you want returned*/
+                            char* type,     /* specific name of element */
+                            int* childNum,  /* child number for iteration */
+                            char* retText,  /* buffer to store return text */
+                            int path_len,   /* length of path */
+                            int flavor_len, /* length of flavor */
+                            int type_len,   /* length of type */
+                            int retText_len /* length of return text buffer */
+                       )
+{
+    int retVal = 0;
+    int i = 0;
+    int length_in = 0;
+
+    PyObject* lib = NULL;
+    PyObject* list = NULL;
+    PyObject* list_item = NULL;
+    
+    char* xmlChild = NULL;
+    char* inPath = NULL;
+    char* inType = NULL;
+    char* inFlavor = NULL;
+    
+    inPath = null_terminate(path,path_len);
+    inFlavor = null_terminate(flavor,flavor_len);
+    inType = null_terminate(type,type_len);
+
+    if (rapptureStarted) {
+        if ((handle) && (*handle != 0)) {
+            lib = getObject(*handle);
+            if (lib) {
+                if(objType(inFlavor) == 1) {
+
+                    list = rpChildren_f(lib, inPath, inFlavor);
+                    if (list) {
+                        retVal = PyList_Size(list);
+                        // check to make sure our node index is within bounds
+                        if (((*childNum)-1) < retVal) {
+                            // get the requested node
+                            list_item = PyList_GetItem(list,(*childNum)-1);
+                            // make node string, borrowed object
+                            xmlChild = PyString_AsString(list_item);
+                            Py_DECREF(list);
+                            // printf("xmlChild = :%s:\n",xmlChild);
+                            if (xmlChild) {
+                                strncpy(retText, xmlChild, retText_len);
+                                length_in = strlen(xmlChild);
+
+                                // fortran-ify the string
+                                if (length_in < retText_len) {
+                                      for (i = length_in; i < retText_len; i++) {
+                                          retText[i] = ' ';
+                                      }
+                                }
+                                // *(retText+retText_len-1) = ' ';
+                            }
+                        }
+                    }
+                    else {
+                        
+                    }
+                }
+            }
+        }
+    }
+
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+    if (inFlavor) {
+        free(inFlavor);
+        inFlavor = NULL;
+    }
+
+    if (inType) {
+        free(inType);
+        inType = NULL;
+    }
+
+
+    return retVal;
+}
+
+ int rp_lib_child_obj ( int* handle, 
+                            char* path, 
+                            char* type, 
+                            int path_len,
+                            int type_len
+                          )
+{
+    int newObjHandle = -1;
+
+    PyObject* lib = NULL;
+    PyObject* list = NULL;
+    
+    char* inPath = NULL;
+    char* inType = NULL;
+
+    inPath = null_terminate(path,path_len);
+    inType = null_terminate(type,type_len);
+
+    if (rapptureStarted) {
+        if ((handle) && (*handle != 0)) {
+            lib = getObject(*handle);
+            
+            if (lib) {
+                list = rpChildren_f(lib, inPath, "object");
+                if (list) {
+                    // store the whole list,
+                    // need to make a way to read the nodes
+                    newObjHandle = storeObject(list);
+                    // Py_DECREF(list);
+                }
+                else {
+                    
+                }
+            }
+        }
+    }
+
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+    if (inType) {
+        free(inType);
+        inType = NULL;
+    }
+
+    return newObjHandle;
+
+}
+
+
+void rp_lib_get( int* handle, /* integer handle of library */
+                   char* path,      /* null terminated path */
+                   char* retText,   /* return text buffer for fortran*/
+                   int path_len,
+                   int retText_len /* length of return text buffer */
+                 )
+{
+    int length_in = 0;
+    int length_out = 0;
+    int i = 0;
+    const char* xmlText = NULL;
+
+    PyObject* lib = NULL;
+    
+    char* inPath = NULL;
+
+    inPath = null_terminate(path,path_len);
+
+    if (rapptureStarted) {
+        if ((handle) && (*handle != 0)) {
+            lib = getObject(*handle);
+            
+            if (lib) {
+                // retObj is a borrowed object 
+                // whose contents must not be modified
+                xmlText = rpGet(lib, inPath);
+                
+                if (xmlText) {
+
+                    length_in = strlen(xmlText);
+                    length_out = retText_len;
+
+                    strncpy(retText, xmlText, length_out);
+
+                    // fortran-ify the string
+                    if (length_in < length_out) {
+                          for (i = length_in; i < length_out; i++) {
+                              retText[i] = ' ';
+                          }
+                    }
+                    *(retText+length_out-1) = ' ';
+                }
+
+            }
+        }
+    }
+
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+}
+
+double rp_lib_get_double( int* handle,   /* integer handle of library */
+                            char* path,    /* null terminated path */
+                            int path_len
+                          )
+{
+    double retVal = 0.0;
+    const char* xmlText = NULL;
+
+    PyObject* lib = NULL;
+    
+    char* inPath = NULL;
+
+    inPath = null_terminate(path,path_len);
+
+    path_len = strlen(inPath) + 1;
+
+    if (rapptureStarted) {
+        if ((handle) && (*handle != 0)) {
+            lib = getObject(*handle);
+            
+            if (lib) {
+                // retObj is a borrowed object 
+                // whose contents must not be modified
+                xmlText = rpGet(lib, inPath);
+                
+                if (xmlText) {
+                    retVal = atof(xmlText);
+                }
+
+            }
+        }
+    }
+
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+    return retVal;
+}
+
+
+void rp_lib_put_str( int* handle, 
+                        char* path, 
+                        char* value, 
+                        int* append,
+                        int path_len,
+                        int value_len
+                      ) 
+{
+    char* inPath = NULL;
+    char* inValue = NULL;
+
+    inPath = null_terminate(path,path_len);
+    inValue = null_terminate(value,value_len);
+
+
+    if (inPath) {
+        path_len = strlen(inPath) + 1;
+    }
+    else {
+        path_len = 0;
+    }
+
+    if (inValue){
+        value_len = strlen(inValue) + 1;
+    }
+    else {
+        value_len = 0;
+    }
+
+    rp_lib_put_id_str(handle,inPath,inValue,NULL,append,path_len,value_len,0);
+
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+    if (inValue) {
+        free(inValue);
+        inValue = NULL;
+    }
+}
+
+
+void rp_lib_put_id_str ( int* handle, 
+                        char* path, 
+                        char* value, 
+                        char* id, 
+                        int* append,
+                        int path_len,
+                        int value_len,
+                        int id_len
+                      ) 
+{
+    PyObject* lib = NULL;
+    
+    char* inPath = NULL;
+    char* inValue = NULL;
+    char* inId = NULL;
+
+    inPath = null_terminate(path,path_len);
+    inValue = null_terminate(value,value_len);
+    inId = null_terminate(id,id_len);
+
+    if (rapptureStarted) {
+        if ((handle) && (*handle != 0)) {
+            lib = getObject(*handle);
+            
+            if (lib) {
+                rpPut(lib, inPath, inValue, inId, *append);
+            }
+        }
+    }
+
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+    if (inValue) {
+        free(inValue);
+        inValue = NULL;
+    }
+
+    if (inId) {
+        free(inId);
+        inId = NULL;
+    }
+
+}
+
+void rp_lib_put_obj( int* handle, 
+                        char* path, 
+                        int* valHandle, 
+                        int* append,
+                        int path_len
+                      ) 
+{
+    char* inPath = NULL;
+
+    inPath = null_terminate(path,path_len);
+
+    if (inPath) {
+        path_len = strlen(inPath) + 1;
+    }
+
+    rp_lib_put_id_obj(handle,inPath,valHandle,NULL,append,path_len,0);
+
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+}
+
+void rp_lib_put_id_obj ( int* handle, 
+                        char* path, 
+                        int* valHandle, 
+                        char* id, 
+                        int* append,
+                        int path_len,
+                        int id_len
+                      ) 
+{
+    PyObject* lib = NULL;
+    PyObject* value = NULL;
+    
+    char* inPath = NULL;
+    char* inId = NULL;
+
+    inPath = null_terminate(path,path_len);
+    inId = null_terminate(id,id_len);
+
+    if (rapptureStarted) {
+        if ((handle) && (*handle != 0)) {
+            lib = getObject(*handle);
+            value = getObject(*valHandle);
+            
+            if (lib && value) {
+                // retObj is a borrowed object 
+                // whose contents must not be modified
+                rpPutObj(lib, inPath, value, inId, *append);
+            }
+        }
+    }
+
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+    if (inId) {
+        free(inId);
+        inId = NULL;
+    }
+
+}
+
+int rp_lib_remove (int* handle, char* path, int path_len) 
+{
+    int newObjHandle = -1;
+
+    PyObject* lib = NULL;
+    PyObject* removedObj = NULL;
+    
+    char* inPath = NULL;
+
+    inPath = null_terminate(path,path_len);
+
+    if (rapptureStarted) {
+        if ((handle) && (*handle != 0)) {
+            lib = getObject(*handle);
+
+            if (lib) {
+                removedObj = rpRemove(lib, inPath);
+                
+                if (removedObj) {
+                    newObjHandle = storeObject(removedObj);
+                    // Py_DECREF(removedObj);
+                }
+
+            }
+        }
+    }
+    
+    if (inPath) {
+        free(inPath);
+        inPath = NULL;
+    }
+
+    return newObjHandle;
+}
+
+int rp_lib_xml_len (int* handle)
+{
+    int length = -1;
+    const char* xmlText = NULL;
+
+    PyObject* lib = NULL;
+
+    if (rapptureStarted) {
+        if ((handle) && (*handle != 0)) {
+            lib = getObject(*handle);
+
+            if (lib) {
+                // dont modify xmlText, borrowed pointer
+                xmlText = rpXml(lib);
+
+                if (xmlText) {
+                    length = strlen(xmlText) + 1;
+                    // printf("len = :%d:\n",length);
+                }
+            }
+        }
+    }
+    return length;
+}
+
+void  rp_lib_xml(int* handle, char* retText, int retText_len)
+{
+    int length_in = 0;
+    int length_out = 0;
+    int i = 0;
+    const char* xmlText = NULL;
+
+    PyObject* lib = NULL;
+    
+    if (rapptureStarted) {
+        if ((handle) && (*handle != 0)) {
+            lib = getObject(*handle);
+
+            if (lib) {
+                xmlText = rpXml(lib);
+                
+                length_in = strlen(xmlText);
+                length_out = retText_len;
+
+                strncpy(retText, xmlText, length_out);
+
+                // fortran-ify the string
+                if (length_in < length_out) {
+                      for (i = length_in; i < length_out; i++) {
+                          retText[i] = ' ';
+                      }
+                }
+                *(retText+length_out-1) = ' ';
+            }
+        }
+    }
+}
+
+int rp_lib_write_xml(int* handle, char* outFile, int outFile_len)
+{
+    int retVal = 0;
+    PyObject* lib = NULL;
+    FILE* outFH = NULL;
+    char* inOutFile = NULL;
+    const char* xmlText = NULL;
+
+    inOutFile = null_terminate(outFile, outFile_len);
+
+    if (inOutFile && (inOutFile != "") ) {
+        outFH = fopen(inOutFile, "w");
+    }
+
+    if (outFH && rapptureStarted) {
+        if ((handle) && (*handle != 0)) {
+            lib = getObject(*handle);
+
+            if (lib) {
+                xmlText = rpXml(lib);
+                retVal = fputs(xmlText,outFH);
+            }
+        }
+    }
+
+    if (outFH) {
+        fclose(outFH);
+        outFH = NULL;
+    }
+
+    if (inOutFile) {
+        free(inOutFile);
+        inOutFile = NULL;
+    }
+
+    return retVal;
+}
+
+void rp_quit()
+{
+
+    // clean up python's memory
+    // shut down the python interpreter
+    // clean up the dictionary
+
+    RpDictEntry DICT_TEMPLATE *hPtr;
+    // RpDictIterator DICT_TEMPLATE iter((RpDict&)*this);                     
+    RpDictIterator DICT_TEMPLATE iter(fortObjDict);
+    
+    hPtr = iter.first();                                                      
+    
+    while (hPtr) {
+        Py_DECREF(*(hPtr->getValue()));
+        hPtr->erase();
+        hPtr = iter.next();                                                   
+    }
+
+    if (fortObjDict.size()) {
+        // probably want to change the warning sometime
+        // printf("\nWARNING: internal dictionary is not empty..deleting\n");
+    }
+
+    rapptureStarted = 0;
+    // Py_Finalize();
+}
+
+int objType( char* flavor) 
+{
+    if (flavor == NULL) {
+        // return a PyObject*
+        return 0;
+    }
+    else if((*flavor == 'o')&&(strncmp(flavor,"object", 6)==0)){
+        // return a PyObject*
+        return 0;
+    }
+    else if ( 
+      ((*flavor == 't')&&(strncmp(flavor,"type", 4) == 0)) 
+    ||((*flavor == 'i')&&(strncmp(flavor,"id", 2) == 0))
+    ||((*flavor == 'c')&&(strncmp(flavor,"component", 9) == 0)))
+    {
+        // return a char*
+        // convert the result to c style strings
+        return 1;
+    }
+    else {
+        // unrecognized format
+        return -1;
+    }
+}
+
+int storeObject(PyObject* objectName) {
+
+    int retVal = -1;
+    int dictKey = fortObjDict.size();
+    int newEntry = 0;
+
+    if (objectName) {
+        // dictionary returns a reference to the inserted value
+        // no error checking to make sure it was successful in entering
+        // the new entry.
+        fortObjDict.set(dictKey,objectName, &newEntry); 
+    }
+    
+    retVal = dictKey;
+    return retVal;
+}
+
+PyObject* getObject(int objKey) {
+
+    PyObject* retVal = *(fortObjDict.find(objKey).getValue());
+
+    if (retVal == *(fortObjDict.getNullEntry().getValue())) {
+        retVal = NULL;
+    }
+
+   return retVal;
+
+}
+
+/* fix buffer overflow possibility*/
+char* null_terminate(char* inStr, int len)
+{
+    int retVal = 0;
+    char* newStr = NULL;
+    char* current = NULL;
+
+    if (inStr) {
+
+        current = inStr+len-1;
+
+        while ((len > 0) && (isspace(*(current)))) {
+            // dont strip off newlines
+
+            if ( (*(current) == '\f')
+              || (*(current) == '\n')
+              || (*(current) == '\r')
+              || (*(current) == '\t')
+              || (*(current) == '\v') )
+            {
+                break;
+            }
+
+            if (--len) {
+                current--;
+            }
+        }
+
+        newStr = (char*) calloc(len+1,(sizeof(char)));
+        strncpy(newStr,inStr,len);
+        *(newStr+len) = '\0';
+
+        retVal++;
+    }
+
+    // return retVal;
+
+    return newStr;
+}
Index: /trunk/src/python/PyRpUnits.cc
===================================================================
--- /trunk/src/python/PyRpUnits.cc	(revision 20)
+++ /trunk/src/python/PyRpUnits.cc	(revision 20)
@@ -0,0 +1,489 @@
+#include <Python.h>
+#include <RpUnits.h>
+
+static PyObject *ErrorObject;
+
+typedef struct {
+	PyObject_HEAD
+	RpUnits* rp_unit;
+} RpUnitsObject;
+
+// static PyTypeObject RpUnitsObjectType;
+
+/* Xxo methods */
+/*
+ * moved this below because forward declaration of RpUnitsObjectType
+ * was causing compiler errors ???
+ *
+static RpUnitsObject*
+newRpUnitsObject(PyObject *arg)
+{
+	RpUnitsObject* self;
+	self = PyObject_New(RpUnitsObject, &RpUnitsObjectType);
+	if (self == NULL)
+		return NULL;
+	self->rp_unit = NULL;
+	return self;
+}
+*/
+
+static void
+RpUnitsObject_dealloc(RpUnitsObject *self)
+{
+    if (self) {
+        if (self->rp_unit){
+            // cant call this right now because destructor is private
+            // delete(self->rp_unit);
+        }
+    
+	    PyObject_Del(self);
+    }
+}
+
+static PyObject*
+RpUnitsObject_getUnits(RpUnitsObject *self)
+{
+    PyObject* rv = NULL;
+
+    if (self->rp_unit){ 
+        rv = PyString_FromString(self->rp_unit->getUnits().c_str());
+    }
+
+    return rv;
+}
+
+static PyObject*
+RpUnitsObject_getUnitsName(RpUnitsObject *self)
+{
+    PyObject* rv = NULL;
+
+    if (self->rp_unit){ 
+        rv = PyString_FromString(self->rp_unit->getUnitsName().c_str());
+    }
+
+    return rv;
+}
+
+static PyObject*
+RpUnitsObject_getExponent(RpUnitsObject *self)
+{
+    PyObject* rv = NULL;
+
+    if (self->rp_unit){ 
+        rv = PyFloat_FromDouble(self->rp_unit->getExponent());
+    }
+
+    return rv;
+}
+
+static PyObject * RpUnitsObject_convert(RpUnitsObject *self, PyObject *args);
+
+static PyObject *
+RpUnitsObject_makeBasis(RpUnitsObject *self, PyObject *args)
+{
+    PyObject* rv = NULL;
+    double inVal = 0;
+    double outVal = 0;
+    int result = 0;
+
+    if (PyTuple_Size(args) > 0) {
+        PyArg_ParseTuple(args, "d", &inVal);
+    }
+    else {
+        PyErr_SetString(PyExc_AttributeError, "incorrect input arguments");
+        return NULL;
+    }
+
+    if (self->rp_unit){ 
+        outVal = self->rp_unit->makeBasis(inVal, &result);
+        if (result) {
+            rv = PyFloat_FromDouble(outVal);
+        }
+        else {
+            PyErr_SetString(PyExc_StandardError, "could not convert to basis");
+        }
+    }
+    else {
+        PyErr_SetString(PyExc_AttributeError, "rp_unit is NULL");
+    }
+
+    return rv;
+}
+
+static PyMethodDef RpUnitsObject_methods[] = {
+    {"getUnits", (PyCFunction)RpUnitsObject_getUnits, METH_NOARGS,
+     "Return the base name of the RpUnitsObject" },
+    {"getUnitsName", (PyCFunction)RpUnitsObject_getUnitsName, METH_NOARGS,
+     "Return the whole (base and exponent) name of the RpUnitsObject" },
+    {"getExponent", (PyCFunction)RpUnitsObject_getExponent, METH_NOARGS,
+     "Return the exponent of the RpUnitsObject" },
+	{"convert", (PyCFunction)RpUnitsObject_convert, METH_VARARGS,
+	 "convert a value from one RpUnits Object to another" },
+	{"makeBasis", (PyCFunction)RpUnitsObject_makeBasis, METH_VARARGS,
+	 "return the basis value of the value provided" },
+    
+    {NULL}  /* Sentinel */
+};
+
+static PyTypeObject RpUnitsObjectType = {
+	/* The ob_type field must be initialized in the module init function
+	 * to be portable to Windows without using C++. */
+	PyObject_HEAD_INIT(NULL)
+	0,			                        /*ob_size*/
+	"RpUnits.RpUnitsObject",		    /*tp_name*/
+	sizeof(RpUnitsObject),	            /*tp_basicsize*/
+	0,			                        /*tp_itemsize*/
+	/* methods */
+	(destructor)RpUnitsObject_dealloc,  /*tp_dealloc*/
+	0,			                        /*tp_print*/
+	0,                                  /*tp_getattr*/
+	0,                                  /*tp_setattr*/
+	0,			                        /*tp_compare*/
+	0,			                        /*tp_repr*/
+	0,			                        /*tp_as_number*/
+	0,			                        /*tp_as_sequence*/
+	0,			                        /*tp_as_mapping*/
+	0,			                        /*tp_hash*/
+    0,                                  /*tp_call*/
+    0,                                  /*tp_str*/
+    0,                                  /*tp_getattro*/
+    0,                                  /*tp_setattro*/
+    0,                                  /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,     /*tp_flags*/
+    "RpUnits Object",                   /*tp_doc*/
+    0,                                  /*tp_traverse*/
+    0,                                  /*tp_clear*/
+    0,                                  /*tp_richcompare*/
+    0,                                  /*tp_weaklistoffset*/
+    0,                                  /*tp_iter*/
+    0,                                  /*tp_iternext*/
+    RpUnitsObject_methods,              /* tp_methods */
+    0,                                  /*tp_members*/
+    0,                                  /*tp_getset*/
+    0,                                  /*tp_base*/
+    0,                                  /*tp_dict*/
+    0,                                  /*tp_descr_get*/
+    0,                                  /*tp_descr_set*/
+    0,                                  /*tp_dictoffset*/
+    0,                                  /*tp_init*/
+    0,                                  /*tp_alloc*/
+    // RpUnitsObject_new,                  /*tp_new*/
+    0,                                  /*tp_new*/
+    0,                                  /*tp_free*/
+    0,                                  /*tp_is_gc*/
+};
+
+static RpUnitsObject*
+newRpUnitsObject(PyObject *arg)
+{
+	RpUnitsObject* self;
+	self = PyObject_New(RpUnitsObject, &RpUnitsObjectType);
+	if (self == NULL)
+		return NULL;
+	self->rp_unit = NULL;
+	return self;
+}
+
+static PyObject *
+RpUnitsObject_convert(RpUnitsObject *self, PyObject *args)
+{
+    PyObject* rv = NULL;
+    // PyObject* toUnits = NULL;
+    RpUnitsObject* toUnits = NULL;
+    PyObject* inVal = NULL;
+    PyObject* argList = NULL;
+    PyObject* outVal = NULL;
+    int result = 0;
+    int argTupleSize = PyTuple_Size(args);
+
+    if (argTupleSize > 0) {
+        PyArg_ParseTuple(args, "O!O", &RpUnitsObjectType, &toUnits, &inVal);
+        argList = PyTuple_New(1);
+        PyTuple_SetItem(argList, 0, inVal);
+        /*
+         * need to make it so user can give any number of variables in arglist
+         * because the new argList is sent to the python conversion fxn where it 
+         * will be parsed in python when c++ calls the conv fxn.
+        PyArg_ParseTuple(args, "O!", &RpUnitsObjectType, &toUnits);
+        if (argTupleSize > 1) {
+            argTupleSize--;
+            inVal = PyTuple_New(argTupleSize);
+            while (argTupleSize)
+            inVal = PyTuple_GetSlice(args,0,argTupleSize);
+        }
+        else {
+            // convertion function needs no arguments???
+            inVal = PyTuple_New(0);
+        }
+        */
+    }
+    else {
+        PyErr_SetString(PyExc_AttributeError, "Not enough arguments");
+        return Py_None;
+    }
+
+    if (self->rp_unit){ 
+        outVal = (PyObject*) self->rp_unit->convert(toUnits->rp_unit, 
+                                                    // (void*)&inVal, 
+                                                    (void*)argList, 
+                                                    &result );
+        if (result) {
+            rv = outVal;
+        }
+    }
+
+    return rv;
+}
+
+/* --------------------------------------------------------------------- */
+
+PyDoc_STRVAR(RpUnits_define_doc, 
+"define(name, basis) -> RpUnitsObject \n\
+\n\
+define RpUnits Object where 'name' is the string name of the units \n\
+and 'basis' is an RpUnitsObject pointer for the basis of the unit \n\
+being created");
+
+static PyObject *
+RpUnits_define(PyObject *self, PyObject *args)
+{
+	RpUnitsObject* newRpUnit;
+    RpUnitsObject* basis = NULL;
+    char* unitsName;
+
+    if (PyTuple_Size(args) > 0) {
+        PyArg_ParseTuple(args, "s|O!", &unitsName, &RpUnitsObjectType,&basis);
+    }
+    else {
+        PyErr_SetString(PyExc_AttributeError, "Not enough arguments");
+        return Py_None;
+    }
+
+	newRpUnit = newRpUnitsObject(args);
+
+	if (newRpUnit == NULL)
+		return NULL;
+
+
+    if (basis && basis->rp_unit) {
+        newRpUnit->rp_unit = RpUnits::define(unitsName, basis->rp_unit);
+    }
+    else {
+        newRpUnit->rp_unit = RpUnits::define(unitsName, NULL);
+    }
+
+    if (newRpUnit->rp_unit == NULL) {
+        // rp_unit was not allocated. 
+        RpUnitsObject_dealloc(newRpUnit);
+        PyErr_SetString(PyExc_AttributeError, "allocating rp_unit failed");
+        return NULL;
+    }
+
+	return (PyObject *)newRpUnit;
+}
+
+void* PyCallback (void* fxnPtr, void* args)
+{
+    PyObject* retVal = NULL;
+    
+    if ((PyObject*)fxnPtr != NULL) {
+        /*
+        retVal = PyObject_CallFunctionObjArgs(  (PyObject*)fxnPtr,
+                                                (PyObject*)args, 
+                                                NULL    );
+        */
+
+        retVal = PyObject_CallObject((PyObject*)fxnPtr,(PyObject*)args);
+    }
+
+    return (void*) retVal;
+
+}
+
+PyDoc_STRVAR(RpUnits_defineConv_doc, 
+"defineConv(fromUnits,toUnits, forwConvFxn, backConvFxn) -> RpUnitsObject\n\
+\n\
+define RpUnits Object where 'name' is the string name of the units \n\
+and 'basis' is an RpUnitsObject pointer for the basis of the unit \n\
+being created");
+
+static PyObject *
+RpUnits_defineConv(PyObject *self, PyObject *args)
+{
+	RpUnitsObject* fromUnit = NULL;
+	RpUnitsObject* toUnit = NULL;
+    PyObject* forwConvFxnStr = NULL;
+    PyObject* backConvFxnStr = NULL;
+
+    RpUnitsObject* newRpUnit = NULL;
+    RpUnits* newConv = NULL;
+
+    if (PyTuple_Size(args) > 0) {
+        PyArg_ParseTuple(args, "O!O!O!O!",&RpUnitsObjectType, &fromUnit, 
+                                          &RpUnitsObjectType, &toUnit, 
+                                          &PyFunction_Type, &forwConvFxnStr,
+                                          &PyFunction_Type, &backConvFxnStr);
+    }
+    else {
+        PyErr_SetString(PyExc_AttributeError, "incorrect input arguments");
+        return NULL;
+    }
+
+    // check to make sure fromUnit and toUnit are populated
+    if ( (fromUnit == NULL) ||
+         (toUnit == NULL) ) {
+        PyErr_SetString(PyExc_AttributeError,
+                "could not retrieve fromUnit or toUnit from argument list");
+    }
+
+    // check to make sure forwConvFxnStr and backConvFxnStr are populated
+    if ( (forwConvFxnStr == NULL) || (backConvFxnStr == NULL) ) {
+        PyErr_SetString(PyExc_AttributeError, 
+                "could not retrieve conversion function argument");
+        return NULL;
+    }
+
+    // make sure we get callable functions and non-null RpUnit Objects
+    if ( PyCallable_Check(forwConvFxnStr) && 
+         PyCallable_Check(backConvFxnStr) &&
+         fromUnit->rp_unit &&
+         toUnit->rp_unit) {
+
+        Py_INCREF(forwConvFxnStr);
+        Py_INCREF(backConvFxnStr);
+        newConv = RpUnits::define(  fromUnit->rp_unit,
+                                    toUnit->rp_unit,
+                                    PyCallback,
+                                    (void*)forwConvFxnStr,
+                                    PyCallback,
+                                    (void*)backConvFxnStr );
+    }
+    else {
+        PyErr_SetString(PyExc_AttributeError, 
+                "could not retrieve conversion function argument");
+        return NULL;
+    }
+
+    if (newConv) {
+        newRpUnit = newRpUnitsObject(args);
+
+        if (newRpUnit) {
+            newRpUnit->rp_unit = newConv;
+        }
+    }
+
+	return (PyObject *)newRpUnit;
+}
+
+PyDoc_STRVAR(RpUnits_find_doc, 
+"find(name) -> RpUnitsObject \n\
+\n\
+search the dictionary of created RpUnits for a unit matching \n\
+the string 'name'");
+
+static PyObject *
+RpUnits_find(PyObject *self, PyObject *args)
+{
+    char* searchUnits = NULL;
+	RpUnits* foundUnits = NULL;
+    RpUnitsObject* returnUnits = NULL;
+
+    if (PyTuple_Size(args) > 0) {
+        PyArg_ParseTuple(args, "s", &searchUnits);
+    }
+    else {
+        PyErr_SetString(PyExc_AttributeError, "incorrect input arguments");
+        return NULL;
+    }
+    
+    foundUnits = RpUnits::find(searchUnits);
+
+    if (foundUnits) {
+        returnUnits = newRpUnitsObject(args);
+
+        if (returnUnits == NULL)
+            return NULL;
+        
+        returnUnits->rp_unit = foundUnits;
+    }
+
+    return (PyObject*) returnUnits;
+    
+}
+
+PyDoc_STRVAR(RpUnits_makeMetric_doc, 
+"find(name) -> RpUnitsObject \n\
+\n\
+search the dictionary of created RpUnits for a unit matching \n\
+the string 'name'");
+
+static PyObject*
+RpUnits_makeMetric(PyObject *self, PyObject *args)
+{
+    RpUnitsObject* units = NULL;
+    int result = 0;
+
+    if (PyTuple_Size(args) > 0) {
+        PyArg_ParseTuple(args, "O!", &RpUnitsObjectType, &units);
+    }
+    else {
+        return NULL;
+    }
+    
+    if (units->rp_unit) {
+        result = RpUnits::makeMetric(units->rp_unit);
+    }
+
+    return PyInt_FromLong((long)result);
+}
+
+/* ---------- */
+
+
+/* List of functions defined in the module */
+
+static PyMethodDef RpUnits_Methods[] = {
+
+	{"define", RpUnits_define, METH_VARARGS,
+        RpUnits_define_doc},
+
+	{"defineConv", RpUnits_defineConv, METH_VARARGS,
+        RpUnits_defineConv_doc},
+    
+	{"find", RpUnits_find, METH_VARARGS,
+        RpUnits_find_doc},
+
+	{"makeMetric", RpUnits_makeMetric, METH_VARARGS,
+        RpUnits_makeMetric_doc},
+    
+	{NULL,		NULL}		/* sentinel */
+};
+
+PyDoc_STRVAR(module_doc, "RpUnits Module for Python.");
+
+/* Initialization function for the module */
+
+PyMODINIT_FUNC
+initRpUnits(void)
+{
+	PyObject *m;
+
+	/* Finalize the type object including setting type of the new type
+	 * object; doing it here is required for portability to Windows 
+	 * without requiring C++. */
+	if (PyType_Ready(&RpUnitsObjectType) < 0)
+		return;
+
+	/* Create the module and add the functions */
+	m = Py_InitModule3("RpUnits", RpUnits_Methods, module_doc);
+
+	/* Add some symbolic constants to the module */
+	if (ErrorObject == NULL) {
+		ErrorObject = PyErr_NewException("RpUnits.error", NULL, NULL);
+		if (ErrorObject == NULL)
+			return;
+	}
+	Py_INCREF(ErrorObject);
+	PyModule_AddObject(m, "error", ErrorObject);
+
+}
