Index: trunk/psModules/src/concepts/pmConcepts.c
===================================================================
--- trunk/psModules/src/concepts/pmConcepts.c	(revision 7310)
+++ trunk/psModules/src/concepts/pmConcepts.c	(revision 7311)
@@ -131,25 +131,44 @@
     }
 
+    bool success = true;                // Success in reading concepts?
     if (source & PM_CONCEPT_SOURCE_CAMERA && !(*read & PM_CONCEPT_SOURCE_CAMERA)) {
-        pmConceptsReadFromCamera(*specs, cell, target);
-        *read |= PM_CONCEPT_SOURCE_CAMERA;
+        if (pmConceptsReadFromCamera(*specs, cell, target)) {
+            *read |= PM_CONCEPT_SOURCE_CAMERA;
+        } else {
+            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from camera configuration.\n");
+            success = false;
+        }
     }
 
     if (source & PM_CONCEPT_SOURCE_DEFAULTS && !(*read & PM_CONCEPT_SOURCE_DEFAULTS)) {
-        pmConceptsReadFromDefaults(*specs, fpa, chip, cell, target);
-        *read |= PM_CONCEPT_SOURCE_DEFAULTS;
+        if (pmConceptsReadFromDefaults(*specs, fpa, chip, cell, target)) {
+            *read |= PM_CONCEPT_SOURCE_DEFAULTS;
+        } else {
+            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from defaults.\n");
+            success = false;
+        }
     }
 
     if (source & PM_CONCEPT_SOURCE_HEADER && !(*read & PM_CONCEPT_SOURCE_HEADER)) {
-        pmConceptsReadFromHeader(*specs, fpa, chip, cell, target);
-        *read |= PM_CONCEPT_SOURCE_HEADER;
-    }
-
+        if (pmConceptsReadFromHeader(*specs, fpa, chip, cell, target)) {
+            *read |= PM_CONCEPT_SOURCE_HEADER;
+        } else {
+            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from header.\n");
+            success = false;
+        }
+    }
+
+    #ifndef OMIT_PSDB
     if (source & PM_CONCEPT_SOURCE_DATABASE && !(*read & PM_CONCEPT_SOURCE_DATABASE)) {
-        pmConceptsReadFromDatabase(*specs, fpa, chip, cell, db, target);
-        *read |= PM_CONCEPT_SOURCE_DATABASE;
-    }
-
-    return true;
+        if (pmConceptsReadFromDatabase(*specs, fpa, chip, cell, db, target)) {
+            *read |= PM_CONCEPT_SOURCE_DATABASE;
+        } else {
+            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from database.\n");
+            success = false;
+        }
+    }
+    #endif
+
+    return success;
 }
 
Index: trunk/psModules/src/concepts/pmConcepts.h
===================================================================
--- trunk/psModules/src/concepts/pmConcepts.h	(revision 7310)
+++ trunk/psModules/src/concepts/pmConcepts.h	(revision 7311)
@@ -6,7 +6,7 @@
 
 // Function to call to parse a concept once it has been read
-typedef psMetadataItem* (*pmConceptParseFunc)(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
+typedef psMetadataItem* (*pmConceptParseFunc)(const psMetadataItem *concept, const psMetadataItem *pattern, const psMetadata *cameraFormat, const pmFPA *fpa, const pmChip *chip, const pmCell *cell);
 // Function to call to format a concept for writing
-typedef psMetadataItem* (*pmConceptFormatFunc)(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
+typedef psMetadataItem* (*pmConceptFormatFunc)(const psMetadataItem *concept, const psMetadata *cameraFormat, const pmFPA *fpa, const pmChip *chip, const pmCell *cell);
 
 // A "concept" specification
Index: trunk/psModules/src/concepts/pmConceptsRead.c
===================================================================
--- trunk/psModules/src/concepts/pmConceptsRead.c	(revision 7310)
+++ trunk/psModules/src/concepts/pmConceptsRead.c	(revision 7311)
@@ -71,6 +71,8 @@
         parsed = parsePlain(concept, spec->blank);
     }
-    if (!parsed)
-        return false;
+    if (!parsed) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s\n", spec->blank->name);
+        return false;
+    }
 
     // Plug the parsed concept into a new psMetadataItem, so each "concept" has its own version that can
@@ -117,5 +119,5 @@
 
     pmHDU *hdu = pmHDUGetLowest(NULL, NULL, cell); // The HDU at the lowest level
-    if (! hdu) {
+    if (!hdu) {
         return false;
     }
@@ -124,9 +126,9 @@
     psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    bool status = true;                 // Status of reading concepts
     while ((specItem = psMetadataGetAndIncrement(specsIter))) {
         pmConceptSpec *spec = specItem->data.V; // The specification
         psString name = specItem->name; // The concept name
         psMetadataItem *conceptItem = psMetadataLookup(cellConfig, name); // The concept, or NULL
-        psMetadataItem *value = NULL; // The value of the concept
         if (conceptItem) {
             if (conceptItem->type == PS_DATA_STRING) {
@@ -138,6 +140,9 @@
                 psFree(nameSource);
                 if (mdok && strlen(source) > 0 && strcasecmp(source, "VALUE") == 0) {
-                    value = conceptItem;
-                    conceptParse(spec, value, cameraFormat, target, NULL, NULL, cell);
+                    if (!conceptParse(spec, conceptItem, cameraFormat, target, NULL, NULL, cell)) {
+                        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from camera "
+                                "configuration\n", name);
+                        status = false;
+                    }
                 } else if (source && (strlen(source) == 0 || strcasecmp(source, "HEADER") != 0)) {
                     // We leave "HEADER" to pmConceptsReadFromHeader
@@ -148,10 +153,14 @@
             } else {
                 // Another type --- should be OK
-                conceptParse(spec, conceptItem, cameraFormat, target, NULL, NULL, cell);
+                if (!conceptParse(spec, conceptItem, cameraFormat, target, NULL, NULL, cell)) {
+                    psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from camera "
+                            "configuration.  It has a weird %s.SOURCE: %s\n", name, name);
+                    status = false;
+                }
             }
         }
     }
     psFree(specsIter);
-    return true;
+    return status;
 }
 
@@ -179,12 +188,16 @@
     psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    bool status = true;                 // Status of reading concepts
     while ((specItem = psMetadataGetAndIncrement(specsIter))) {
         pmConceptSpec *spec = specItem->data.V; // The specification
         psString name = specItem->name; // The concept name
         psMetadataItem *conceptItem = psMetadataLookup(defaults, name); // The concept, or NULL
-        conceptParse(spec, conceptItem, cameraFormat, target, fpa, chip, cell);
+        if (conceptItem && !conceptParse(spec, conceptItem, cameraFormat, target, fpa, chip, cell)) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from DEFAULTS.\n", name);
+            status = false;
+        }
     }
     psFree(specsIter);
-    return true;
+    return status;
 }
 
@@ -213,4 +226,5 @@
     psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    bool status = true;                 // Status of reading concepts
     while ((specItem = psMetadataGetAndIncrement(specsIter))) {
         pmConceptSpec *spec = specItem->data.V; // The specification
@@ -257,8 +271,11 @@
 
         // This will also clean up the name
-        conceptParse(spec, headerItem, cameraFormat, target, fpa, chip, cell);
+        if (headerItem && !conceptParse(spec, headerItem, cameraFormat, target, fpa, chip, cell)) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from header.\n", name);
+            status = false;
+        }
     }
     psFree(specsIter);
-    return true;
+    return status;
 }
 
@@ -294,4 +311,5 @@
     psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    bool status = true;                 // Status of reading concepts
     while ((specItem = psMetadataGetAndIncrement(specsIter))) {
         pmConceptSpec *spec = specItem->data.V; // The specification
@@ -374,5 +392,9 @@
 
                     // Now we have the result
-                    conceptParse(spec, conceptItem, cameraFormat, target, fpa, chip, cell);
+                    if (!conceptParse(spec, conceptItem, cameraFormat, target, fpa, chip, cell)) {
+                        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from database.\n",
+                                name);
+                        status = false;
+                    }
 
                 }
@@ -385,5 +407,5 @@
     psFree(specsIter);
 
-    return true;
+    return status;
     #endif
 }
Index: trunk/psModules/src/concepts/pmConceptsStandard.c
===================================================================
--- trunk/psModules/src/concepts/pmConceptsStandard.c	(revision 7310)
+++ trunk/psModules/src/concepts/pmConceptsStandard.c	(revision 7311)
@@ -69,5 +69,5 @@
                     sscanf(concept->data.V, "%d %d %f", &big, &medium, &small) != 3)
             {
-                psError(PS_ERR_IO, true, "Cannot interpret FPA.RA: %s\n", concept->data.V);
+                psError(PS_ERR_UNKNOWN, true, "Cannot interpret FPA.RA: %s\n", concept->data.V);
                 break;
             }
@@ -80,5 +80,5 @@
         break;
     default:
-        psError(PS_ERR_IO, true, "%s concept is of an unexpected type: %x\n", pattern->name, concept->type);
+        psError(PS_ERR_UNKNOWN, true, "%s concept is of an unexpected type: %x\n", pattern->name, concept->type);
         return NULL;
     }
@@ -171,9 +171,8 @@
     assert(pattern);
 
-    psRegion *trimsec = psAlloc(sizeof(psRegion)); // Make space for a psRegion (usually passed by value)
+    psRegion *trimsec = psRegionAlloc(0, 0, 0, 0);
 
     if (concept->type != PS_DATA_STRING) {
-        psError(PS_ERR_IO, true, "CELL.TRIMSEC after read is not of type STR (%x)\n", concept->type);
-        *trimsec = psRegionSet(0.0, 0.0, 0.0, 0.0);
+        psError(PS_ERR_UNKNOWN, true, "CELL.TRIMSEC after read is not of type STR (%x)\n", concept->type);
     } else {
         *trimsec = psRegionFromString(concept->data.V);
@@ -231,5 +230,5 @@
         }
     default:
-        psError(PS_ERR_IO, true, "CELL.BIASSEC after read is not of type STRING or LIST --- assuming "
+        psError(PS_ERR_UNKNOWN, true, "CELL.BIASSEC after read is not of type STRING or LIST --- assuming "
                 "blank.\n");
     }
@@ -259,5 +258,5 @@
                     (strcmp(pattern->name, "CELL.YBIN") == 0 && sscanf(binString, "%*d %d", &binning) != 1 &&
                      sscanf(binString, "%*d,%d", &binning) != 1)) {
-                psError(PS_ERR_IO, true, "Unable to parse string to get %s: %s\n", pattern->name, binString);
+                psError(PS_ERR_UNKNOWN, true, "Unable to parse string to get %s: %s\n", pattern->name, binString);
             }
         }
@@ -269,5 +268,5 @@
         TYPE_CASE(binning, concept, S32);
     default:
-        psError(PS_ERR_IO, true, "Note sure how to parse %s of type %x --- assuming 1.\n", pattern->name,
+        psError(PS_ERR_UNKNOWN, true, "Note sure how to parse %s of type %x --- assuming 1.\n", pattern->name,
                 concept->type);
     }
@@ -290,5 +289,5 @@
     psString sys = concept->data.V;     // The time system string
     if (concept->type != PS_DATA_STRING || strlen(sys) <= 0) {
-        psError(PS_ERR_IO, true, "Can't interpret CELL.TIMESYS --- assuming UTC.\n");
+        psError(PS_ERR_UNKNOWN, true, "Can't interpret CELL.TIMESYS --- assuming UTC.\n");
     } else if (strcasecmp(sys, "TAI") == 0) {
         timeSys = PS_TIME_TAI;
@@ -300,5 +299,5 @@
         timeSys = PS_TIME_TT;
     } else {
-        psError(PS_ERR_IO, true, "Can't interpret CELL.TIMESYS --- assuming UTC.\n");
+        psError(PS_ERR_UNKNOWN, true, "Can't interpret CELL.TIMESYS --- assuming UTC.\n");
     }
 
@@ -334,10 +333,14 @@
     // Get format
     psMetadata *formats = psMetadataLookupMD(&mdok, cameraFormat, "FORMATS");
-    if (!mdok || !formats)
+    if (!mdok || !formats) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to find FORMATS in camera configuration.\n");
         return NULL;
+    }
 
     psString timeFormat = psMetadataLookupStr(&mdok, formats, "CELL.TIME");
-    if (!mdok || !timeFormat || !strlen(timeFormat))
+    if (!mdok || !timeFormat || !strlen(timeFormat)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to find CELL.TIME in FORMATS.\n");
         return NULL;
+    }
 
     // Parse the time format
@@ -385,5 +388,5 @@
             psMetadataItem *timeItem = psListGet(dateTime, PS_LIST_HEAD + 1); // Item containing the time
             if (dateItem->type != PS_DATA_STRING) {
-                psError(PS_ERR_IO, true, "Date is not of type STR.\n");
+                psError(PS_ERR_UNKNOWN, true, "Date is not of type STR.\n");
                 return NULL;
             }
@@ -392,5 +395,5 @@
             if (sscanf(dateString, "%d-%d-%d", &year, &month, &day) != 3 &&
                     sscanf(dateString, "%d/%d/%d", &year, &month, &day) != 3) {
-                psError(PS_ERR_IO, true, "Unable to read date: %s\n", dateString);
+                psError(PS_ERR_UNKNOWN, true, "Unable to read date: %s\n", dateString);
                 return NULL;
             }
@@ -408,7 +411,13 @@
                 year = temp;
             }
-            if (pre2000Time || year < 2000) {
-                year += 2000;
-            }
+            if (year < 100) {
+                if (pre2000Time) {
+                    year += 1900;
+                } else {
+                    year += 2000;
+                }
+            }
+            sprintf(dateString,"%04d-%02d-%02d", year, month, day);
+
             psString timeString = NULL; // The string with the time
             if (timeItem->type == PS_DATA_STRING) {
@@ -427,5 +436,5 @@
                     TYPE_CASE(seconds, timeItem, F64);
                 default:
-                    psError(PS_ERR_IO, true, "Time is not of an expected type: %x\n", timeItem->type);
+                    psError(PS_ERR_UNKNOWN, true, "Time is not of an expected type: %x\n", timeItem->type);
                     return NULL;
                 }
@@ -440,4 +449,5 @@
             psStringAppend(&dateTimeString, "%sT%s", dateString, timeString);
             time = psTimeFromISO(dateTimeString, timeSys);
+            psFree(dateTimeString);
             break;
         }
@@ -463,5 +473,6 @@
                 time = psTimeFromMJD(timeValue);
             } else {
-                psError(PS_ERR_IO, true, "Not sure how to parse CELL.TIME (%f) --- trying JD\n", timeValue);
+                psError(PS_ERR_UNKNOWN, true, "Not sure how to parse CELL.TIME (%f) --- trying JD\n",
+                        timeValue);
                 time = psTimeFromJD(timeValue);
             }
@@ -475,5 +486,6 @@
                 time = psTimeFromMJD(timeValue);
             } else {
-                psError(PS_ERR_IO, true, "Not sure how to parse CELL.TIME (%f) --- trying JD\n", timeValue);
+                psError(PS_ERR_UNKNOWN, true, "Not sure how to parse CELL.TIME (%f) --- trying JD\n",
+                        timeValue);
                 time = psTimeFromJD(timeValue);
             }
@@ -481,5 +493,5 @@
         }
     default:
-        psError(PS_ERR_IO, true, "Unable to parse CELL.TIME.\n");
+        psError(PS_ERR_UNKNOWN, true, "Unable to parse CELL.TIME.\n");
         return NULL;
     }
@@ -526,5 +538,5 @@
         TYPE_CASE(offset, concept, S32);
     default:
-        psError(PS_ERR_IO, true, "Concept %s is not of integer type, as expected.\n", pattern->name);
+        psError(PS_ERR_UNKNOWN, true, "Concept %s is not of integer type, as expected.\n", pattern->name);
         return NULL;
     }
@@ -724,13 +736,13 @@
         // XXX: Couldn't be bothered doing these right now
         if (pre2000Time) {
-            psError(PS_ERR_IO, true, "Don't you realise it's the twenty-first century?\n");
+            psError(PS_ERR_UNKNOWN, true, "Don't you realise it's the twenty-first century?\n");
             return NULL;
         }
         if (backwardsTime) {
-            psError(PS_ERR_IO, true, "You want it BACKWARDS?  Not right now, thanks.\n");
+            psError(PS_ERR_UNKNOWN, true, "You want it BACKWARDS?  Not right now, thanks.\n");
             return NULL;
         }
         if (usaTime) {
-            psError(PS_ERR_IO, true, "USA?  No OK --- yet.\n");
+            psError(PS_ERR_UNKNOWN, true, "USA?  No OK.\n");
             return NULL;
         }
@@ -778,5 +790,5 @@
 
     if (concept->type != PS_TYPE_S32) {
-        psError(PS_ERR_IO, true, "Concept %s is not of type S32, as expected.\n", concept->name);
+        psError(PS_ERR_UNKNOWN, true, "Concept %s is not of type S32, as expected.\n", concept->name);
         return NULL;
     }
