Better checking of library result values.
[gedcom-parse.git] / gom / gom_internal.h
1 /* General header for the Gedcom object model.
2    Copyright (C) 2002 The Genes Development Team
3    This file is part of the Gedcom parser library.
4    Contributed by Peter Verthez <Peter.Verthez@advalvas.be>, 2002.
5
6    The Gedcom parser library is free software; you can redistribute it
7    and/or modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The Gedcom parser library is distributed in the hope that it will be
12    useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the Gedcom parser library; if not, write to the
18    Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 /* $Id$ */
22 /* $Name$ */
23
24 #ifndef __GOM_INTERNAL_H
25 #define __GOM_INTERNAL_H
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <libintl.h>
30 #include "gom.h"
31 #include "gedcom.h"
32 #ifdef WITH_DMALLOC
33 #include <dmalloc.h>
34 #endif
35       
36 #define _(string) gettext(string)
37 #define N_(string) (string)
38
39 typedef enum {
40   T_NULL,
41   
42   T_header, T_submission, T_submitter, T_family, T_individual,
43   T_multimedia, T_note, T_repository, T_source, T_user_rec,
44   
45   T_address, T_event, T_place, T_source_citation, T_text,
46   T_note_sub, T_multimedia_link, T_lds_event, T_user_ref_number,
47   T_change_date, T_personal_name, T_family_link, T_pedigree,
48   T_association, T_source_event, T_source_description
49 } OBJ_TYPE;
50
51 struct Gom_ctxt_struct {
52   int ctxt_type;
53   OBJ_TYPE obj_type;
54   void* ctxt_ptr;
55 };
56
57 typedef struct Gom_ctxt_struct *Gom_ctxt;
58
59 Gom_ctxt make_gom_ctxt(int ctxt_type, OBJ_TYPE obj_type, void *ctxt_ptr);
60 void destroy_gom_ctxt(Gom_ctxt ctxt);
61 void gom_cast_error(char* file, int line, OBJ_TYPE expected, OBJ_TYPE found);
62 void gom_unexpected_context(char* file, int line, OBJ_TYPE found);
63
64 #define MAKE_GOM_CTXT(CTXT_TYPE, STRUCTTYPE, CTXT_PTR)                        \
65   make_gom_ctxt(CTXT_TYPE, T_ ## STRUCTTYPE, CTXT_PTR)
66
67 #define SAFE_CTXT_CAST(STRUCTTYPE, VAL)                                       \
68   (((VAL)->obj_type == T_ ## STRUCTTYPE) ?                                    \
69    (VAL)->ctxt_ptr :                                                          \
70    (gom_cast_error(__FILE__, __LINE__, T_ ## STRUCTTYPE, (VAL)->obj_type),    \
71     (VAL)->ctxt_ptr))
72
73 #define SAFE_FREE(PTR)                                                        \
74   if (PTR) {                                                                  \
75     free(PTR);                                                                \
76     PTR = NULL;                                                               \
77   }
78
79 #define UNEXPECTED_CONTEXT(CTXT_TYPE)                                         \
80   gom_unexpected_context(__FILE__, __LINE__, CTXT_TYPE)
81
82 void gom_mem_error(char *filename, int line);
83
84 #define MEMORY_ERROR gom_mem_error(__FILE__, __LINE__)
85
86 void def_rec_end(Gedcom_rec rec, Gedcom_ctxt self);
87 void def_elt_end(Gedcom_elt elt, Gedcom_ctxt parent, Gedcom_ctxt self,
88                  Gedcom_val parsed_value);
89 void set_xref_type(struct xref_value *xr, char* str);
90
91 typedef enum {
92   WITHOUT_NL,
93   WITH_NL
94 } NL_TYPE;
95
96 char* concat_strings(NL_TYPE type, char *str1, const char *str2);
97 struct date_value* dup_date(struct date_value dv);
98 struct age_value*  dup_age(struct age_value age);
99
100 /* Doubly-linked list, but last rec->next is NULL (doesn't go to first rec) */
101 #define LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                             \
102   {                                                                           \
103     struct STRUCTTYPE *_local_obj = VAL;                                      \
104     if (! FIRSTVAL) {                                                         \
105       VAL->next = NULL;                                                       \
106       VAL->previous = _local_obj;                                             \
107       FIRSTVAL = VAL;                                                         \
108     }                                                                         \
109     else {                                                                    \
110       VAL->next = NULL;                                                       \
111       FIRSTVAL->previous->next = VAL;                                         \
112       VAL->previous = FIRSTVAL->previous;                                     \
113       FIRSTVAL->previous = VAL;                                               \
114     }                                                                         \
115   }
116
117 #define MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                             \
118   {                                                                           \
119     VAL = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE));             \
120     if (! VAL)                                                                \
121       MEMORY_ERROR;                                                           \
122     else {                                                                    \
123       memset (VAL, 0, sizeof(struct STRUCTTYPE));                             \
124       LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                               \
125     }                                                                         \
126   }
127
128 void NULL_DESTROY(void* anything);
129
130 #define DESTROY_CHAIN_ELTS(STRUCTTYPE, FIRSTVAL, DESTROYFUNC)                 \
131   {                                                                           \
132     if (FIRSTVAL) {                                                           \
133       struct STRUCTTYPE *runner, *next;                                       \
134       runner = FIRSTVAL;                                                      \
135       while (runner) {                                                        \
136         next = runner->next;                                                  \
137         DESTROYFUNC(runner);                                                  \
138         SAFE_FREE(runner);                                                    \
139         runner = next;                                                        \
140       }                                                                       \
141     }                                                                         \
142   }
143
144 #define _REC_PARAMS_ Gedcom_rec rec, int level, Gedcom_val xref, char *tag,   \
145                      char *raw_value, int parsed_tag, Gedcom_val parsed_value
146
147 #define _ELT_PARAMS_ Gedcom_elt elt, Gedcom_ctxt parent, int level, char *tag,\
148                      char *raw_value, int parsed_tag, Gedcom_val parsed_value
149
150 #define REC_CB(STRUCTTYPE,CB_NAME,FUNC)                                       \
151   Gedcom_ctxt CB_NAME(_REC_PARAMS_)                                           \
152   {                                                                           \
153     struct xref_value* xr = GEDCOM_XREF_PTR(xref);                            \
154     if (! xr->object)                                                         \
155       xr->object = (Gedcom_ctxt) FUNC(xr->string);                            \
156     return (Gedcom_ctxt) MAKE_GOM_CTXT(rec, STRUCTTYPE, xr->object);          \
157   }
158
159 #define GET_REC_BY_XREF(STRUCTTYPE,XREF_TYPE,FUNC_NAME)                       \
160   struct STRUCTTYPE *FUNC_NAME(char *xrefstr)                                 \
161   {                                                                           \
162     struct xref_value* xr = gedcom_get_by_xref(xrefstr);                      \
163     if (xr && (xr->type == XREF_TYPE) && xr->object)                          \
164       return (struct STRUCTTYPE*)(xr->object);                                \
165     else                                                                      \
166       return NULL;                                                            \
167   }
168
169 #define STRING_CB(STRUCTTYPE,CB_NAME,FIELD)                                   \
170   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
171   {                                                                           \
172     char *str = GEDCOM_STRING(parsed_value);                                  \
173     struct STRUCTTYPE *obj                                                    \
174       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
175     if (obj) {                                                                \
176       obj->FIELD = strdup(str);                                               \
177       if (! obj->FIELD) {                                                     \
178         MEMORY_ERROR;                                                         \
179         return NULL;                                                          \
180       }                                                                       \
181     }                                                                         \
182     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
183   }
184
185 #define DATE_CB(STRUCTTYPE,CB_NAME,FIELD)                                     \
186   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
187   {                                                                           \
188     struct date_value dv = GEDCOM_DATE(parsed_value);                         \
189     struct STRUCTTYPE *obj                                                    \
190       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
191     if (obj) {                                                                \
192       obj->FIELD = dup_date(dv);                                              \
193       if (! obj->FIELD) {                                                     \
194         MEMORY_ERROR;                                                         \
195         return NULL;                                                          \
196       }                                                                       \
197     }                                                                         \
198     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
199   }
200
201 #define AGE_CB(STRUCTTYPE,CB_NAME,FIELD)                                      \
202   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
203   {                                                                           \
204     struct age_value age = GEDCOM_AGE(parsed_value);                          \
205     struct STRUCTTYPE *obj                                                    \
206       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
207     if (obj) {                                                                \
208       obj->FIELD = dup_age(age);                                              \
209       if (! obj->FIELD) {                                                     \
210         MEMORY_ERROR;                                                         \
211         return NULL;                                                          \
212       }                                                                       \
213     }                                                                         \
214     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
215   }
216
217 #define XREF_CB(STRUCTTYPE,CB_NAME,FIELD,FUNC)                                \
218   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
219   {                                                                           \
220     struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);                    \
221     struct STRUCTTYPE *obj                                                    \
222       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
223     if (! xr->object)                                                         \
224       xr->object = (Gedcom_ctxt) FUNC(xr->string);                            \
225     if (obj) obj->FIELD = xr;                                                 \
226     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
227   }
228
229 #define XREF_LIST_CB(STRUCTTYPE,CB_NAME,FIELD,FUNC)                           \
230   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
231   {                                                                           \
232     struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);                    \
233     struct STRUCTTYPE *obj                                                    \
234       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
235     struct xref_list *xrl;                                                    \
236     if (! xr->object)                                                         \
237       xr->object = (Gedcom_ctxt) FUNC(xr->string);                            \
238     MAKE_CHAIN_ELT(xref_list, obj->FIELD, xrl);                               \
239     xrl->xref = xr;                                                           \
240     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
241   }
242
243 #define NULL_CB(STRUCTTYPE,CB_NAME)                                           \
244   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
245   {                                                                           \
246     struct STRUCTTYPE *obj                                                    \
247       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
248     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
249   }
250
251 #endif /* __GOM_INTERNAL_H */