Removed support for testing with dmalloc (valgrind is better...).
[gedcom-parse.git] / gom / gom_internal.h
index b24c28953869348393643018e98843ffa3c4159f..0ef609bd3dc6414a51a4145b1d891f86940e4611 100644 (file)
 #include <libintl.h>
 #include "gom.h"
 #include "gedcom.h"
-#ifdef WITH_DMALLOC
-#include <dmalloc.h>
-#endif
       
 #define _(string) gettext(string)
 #define N_(string) (string)
 
+#ifdef __GNUC__
+#define UNUSED __attribute__((unused))
+#else
+#define UNUSED
+#endif
+
 typedef enum {
   T_NULL,
   
@@ -48,6 +51,12 @@ typedef enum {
   T_association, T_source_event, T_source_description
 } OBJ_TYPE;
 
+/* Assumptions for context:
+    - In case of error, NULL is passed as context
+    - If not NULL, the ctxt_ptr of the context is not NULL also
+    - UNEXPECTED_CONTEXT is not treated as an error, but as a warning
+*/
+
 struct Gom_ctxt_struct {
   int ctxt_type;
   OBJ_TYPE obj_type;
@@ -58,8 +67,10 @@ typedef struct Gom_ctxt_struct *Gom_ctxt;
 
 Gom_ctxt make_gom_ctxt(int ctxt_type, OBJ_TYPE obj_type, void *ctxt_ptr);
 void destroy_gom_ctxt(Gom_ctxt ctxt);
-void gom_cast_error(char* file, int line, OBJ_TYPE expected, OBJ_TYPE found);
-void gom_unexpected_context(char* file, int line, OBJ_TYPE found);
+void gom_cast_error(const char* file, int line,
+                   OBJ_TYPE expected, OBJ_TYPE found);
+void gom_no_context(const char* file, int line);
+void gom_unexpected_context(const char* file, int line, OBJ_TYPE found);
 
 #define MAKE_GOM_CTXT(CTXT_TYPE, STRUCTTYPE, CTXT_PTR)                        \
   make_gom_ctxt(CTXT_TYPE, T_ ## STRUCTTYPE, CTXT_PTR)
@@ -79,10 +90,17 @@ void gom_unexpected_context(char* file, int line, OBJ_TYPE found);
 #define UNEXPECTED_CONTEXT(CTXT_TYPE)                                         \
   gom_unexpected_context(__FILE__, __LINE__, CTXT_TYPE)
 
+#define NO_CONTEXT                                                            \
+  gom_no_context(__FILE__, __LINE__)
+
+void gom_mem_error(const char *filename, int line);
+
+#define MEMORY_ERROR gom_mem_error(__FILE__, __LINE__)
+
 void def_rec_end(Gedcom_rec rec, Gedcom_ctxt self);
-void def_elt_end(Gedcom_elt elt, Gedcom_ctxt parent, Gedcom_ctxt self,
-                Gedcom_val parsed_value);
-void set_xref_type(struct xref_value *xr, char* str);
+void def_elt_end(Gedcom_elt elt, Gedcom_ctxt parent,
+                Gedcom_ctxt self, Gedcom_val parsed_value);
+void set_xref_type(struct xref_value *xr, const char* str);
 
 typedef enum {
   WITHOUT_NL,
@@ -113,8 +131,12 @@ struct age_value*  dup_age(struct age_value age);
 #define MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                             \
   {                                                                           \
     VAL = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE));             \
-    memset (VAL, 0, sizeof(struct STRUCTTYPE));                               \
-    LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                                 \
+    if (! VAL)                                                                \
+      MEMORY_ERROR;                                                           \
+    else {                                                                    \
+      memset (VAL, 0, sizeof(struct STRUCTTYPE));                             \
+      LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                               \
+    }                                                                         \
   }
 
 void NULL_DESTROY(void* anything);
@@ -133,11 +155,15 @@ void NULL_DESTROY(void* anything);
     }                                                                         \
   }
 
-#define _REC_PARAMS_ Gedcom_rec rec, int level, Gedcom_val xref, char *tag,   \
-                     char *raw_value, int parsed_tag, Gedcom_val parsed_value
+#define _REC_PARAMS_ Gedcom_rec rec UNUSED, int level UNUSED,                 \
+                     Gedcom_val xref UNUSED, char *tag UNUSED,                \
+                     char *raw_value UNUSED, int parsed_tag UNUSED,           \
+                     Gedcom_val parsed_value UNUSED
 
-#define _ELT_PARAMS_ Gedcom_elt elt, Gedcom_ctxt parent, int level, char *tag,\
-                     char *raw_value, int parsed_tag, Gedcom_val parsed_value
+#define _ELT_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED,        \
+                     int level UNUSED, char *tag UNUSED,                      \
+                     char *raw_value UNUSED, int parsed_tag UNUSED,           \
+                     Gedcom_val parsed_value UNUSED
 
 #define REC_CB(STRUCTTYPE,CB_NAME,FUNC)                                       \
   Gedcom_ctxt CB_NAME(_REC_PARAMS_)                                           \
@@ -145,11 +171,14 @@ void NULL_DESTROY(void* anything);
     struct xref_value* xr = GEDCOM_XREF_PTR(xref);                            \
     if (! xr->object)                                                         \
       xr->object = (Gedcom_ctxt) FUNC(xr->string);                            \
-    return (Gedcom_ctxt) MAKE_GOM_CTXT(rec, STRUCTTYPE, xr->object);          \
+    if (xr->object)                                                           \
+      return (Gedcom_ctxt) MAKE_GOM_CTXT(rec, STRUCTTYPE, xr->object);        \
+    else                                                                      \
+      return NULL;                                                            \
   }
 
 #define GET_REC_BY_XREF(STRUCTTYPE,XREF_TYPE,FUNC_NAME)                       \
-  struct STRUCTTYPE *FUNC_NAME(char *xrefstr)                                 \
+  struct STRUCTTYPE *FUNC_NAME(const char *xrefstr)                           \
   {                                                                           \
     struct xref_value* xr = gedcom_get_by_xref(xrefstr);                      \
     if (xr && (xr->type == XREF_TYPE) && xr->object)                          \
@@ -161,65 +190,123 @@ void NULL_DESTROY(void* anything);
 #define STRING_CB(STRUCTTYPE,CB_NAME,FIELD)                                   \
   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
   {                                                                           \
-    char *str = GEDCOM_STRING(parsed_value);                                  \
-    struct STRUCTTYPE *obj                                                    \
-      = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
-    if (obj) obj->FIELD = strdup(str);                                        \
-    return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
+    Gom_ctxt result = NULL;                                                   \
+    if (! parent)                                                             \
+      NO_CONTEXT;                                                             \
+    else {                                                                    \
+      struct STRUCTTYPE *obj                                                  \
+        = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
+      if (obj) {                                                              \
+        char *str = GEDCOM_STRING(parsed_value);                              \
+        obj->FIELD = strdup(str);                                             \
+        if (! obj->FIELD)                                                     \
+         MEMORY_ERROR;                                                       \
+        else                                                                  \
+          result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                       \
+      }                                                                       \
+    }                                                                         \
+    return (Gedcom_ctxt)result;                                               \
   }
 
 #define DATE_CB(STRUCTTYPE,CB_NAME,FIELD)                                     \
   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
   {                                                                           \
-    struct date_value dv = GEDCOM_DATE(parsed_value);                         \
-    struct STRUCTTYPE *obj                                                    \
-      = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
-    if (obj) obj->FIELD = dup_date(dv);                                       \
-    return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
+    Gom_ctxt result = NULL;                                                   \
+    if (! parent)                                                             \
+      NO_CONTEXT;                                                             \
+    else {                                                                    \
+      struct STRUCTTYPE *obj                                                  \
+        = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
+      if (obj) {                                                              \
+        struct date_value dv = GEDCOM_DATE(parsed_value);                     \
+        obj->FIELD = dup_date(dv);                                            \
+        if (! obj->FIELD)                                                     \
+         MEMORY_ERROR;                                                       \
+        else                                                                  \
+          result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                       \
+      }                                                                       \
+    }                                                                         \
+    return (Gedcom_ctxt)result;                                               \
   }
 
 #define AGE_CB(STRUCTTYPE,CB_NAME,FIELD)                                      \
   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
   {                                                                           \
-    struct age_value age = GEDCOM_AGE(parsed_value);                          \
-    struct STRUCTTYPE *obj                                                    \
-      = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
-    if (obj) obj->FIELD = dup_age(age);                                       \
-    return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
+    Gom_ctxt result = NULL;                                                   \
+    if (! parent)                                                             \
+      NO_CONTEXT;                                                             \
+    else {                                                                    \
+      struct STRUCTTYPE *obj                                                  \
+        = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
+      if (obj) {                                                              \
+        struct age_value age = GEDCOM_AGE(parsed_value);                      \
+        obj->FIELD = dup_age(age);                                            \
+        if (! obj->FIELD)                                                     \
+         MEMORY_ERROR;                                                       \
+        else                                                                  \
+          result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                       \
+      }                                                                       \
+    }                                                                         \
+    return (Gedcom_ctxt)result;                                               \
   }
 
 #define XREF_CB(STRUCTTYPE,CB_NAME,FIELD,FUNC)                                \
   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
   {                                                                           \
-    struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);                    \
-    struct STRUCTTYPE *obj                                                    \
-      = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
-    if (! xr->object)                                                         \
-      xr->object = (Gedcom_ctxt) FUNC(xr->string);                            \
-    if (obj) obj->FIELD = xr;                                                 \
-    return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
+    Gom_ctxt result = NULL;                                                   \
+    if (! parent)                                                             \
+      NO_CONTEXT;                                                             \
+    else {                                                                    \
+      struct STRUCTTYPE *obj                                                  \
+        = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
+      struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);                  \
+      if (! xr->object)                                                       \
+        xr->object = (Gedcom_ctxt) FUNC(xr->string);                          \
+      if (obj) {                                                              \
+       obj->FIELD = xr;                                                      \
+        result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                         \
+      }                                                                       \
+    }                                                                         \
+    return (Gedcom_ctxt)result;                                               \
   }
 
 #define XREF_LIST_CB(STRUCTTYPE,CB_NAME,FIELD,FUNC)                           \
   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
   {                                                                           \
-    struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);                    \
-    struct STRUCTTYPE *obj                                                    \
-      = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
-    struct xref_list *xrl;                                                    \
-    if (! xr->object)                                                         \
-      xr->object = (Gedcom_ctxt) FUNC(xr->string);                            \
-    MAKE_CHAIN_ELT(xref_list, obj->FIELD, xrl);                               \
-    xrl->xref = xr;                                                           \
-    return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
+    Gom_ctxt result = NULL;                                                   \
+    if (! parent)                                                             \
+      NO_CONTEXT;                                                             \
+    else {                                                                    \
+      struct STRUCTTYPE *obj                                                  \
+        = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
+      struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);                  \
+      struct xref_list *xrl;                                                  \
+      if (! xr->object)                                                       \
+        xr->object = (Gedcom_ctxt) FUNC(xr->string);                          \
+      if (obj) {                                                              \
+        MAKE_CHAIN_ELT(xref_list, obj->FIELD, xrl);                           \
+        if (xrl) {                                                            \
+          xrl->xref = xr;                                                     \
+          result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                       \
+        }                                                                     \
+      }                                                                       \
+    }                                                                         \
+    return (Gedcom_ctxt)result;                                               \
   }
 
 #define NULL_CB(STRUCTTYPE,CB_NAME)                                           \
   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
   {                                                                           \
-    struct STRUCTTYPE *obj                                                    \
-      = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
-    return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
+    Gom_ctxt result = NULL;                                                   \
+    if (! parent)                                                             \
+      NO_CONTEXT;                                                             \
+    else {                                                                    \
+      struct STRUCTTYPE *obj                                                  \
+        = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
+      if (obj)                                                                \
+       result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                         \
+    }                                                                         \
+    return (Gedcom_ctxt)result;                                               \
   }
 
 #endif /* __GOM_INTERNAL_H */