Better checking of library return 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     memset (VAL, 0, sizeof(struct STRUCTTYPE));                               \
121     LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                                 \
122   }
123
124 void NULL_DESTROY(void* anything);
125
126 #define DESTROY_CHAIN_ELTS(STRUCTTYPE, FIRSTVAL, DESTROYFUNC)                 \
127   {                                                                           \
128     if (FIRSTVAL) {                                                           \
129       struct STRUCTTYPE *runner, *next;                                       \
130       runner = FIRSTVAL;                                                      \
131       while (runner) {                                                        \
132         next = runner->next;                                                  \
133         DESTROYFUNC(runner);                                                  \
134         SAFE_FREE(runner);                                                    \
135         runner = next;                                                        \
136       }                                                                       \
137     }                                                                         \
138   }
139
140 #define _REC_PARAMS_ Gedcom_rec rec, int level, Gedcom_val xref, char *tag,   \
141                      char *raw_value, int parsed_tag, Gedcom_val parsed_value
142
143 #define _ELT_PARAMS_ Gedcom_elt elt, Gedcom_ctxt parent, int level, char *tag,\
144                      char *raw_value, int parsed_tag, Gedcom_val parsed_value
145
146 #define REC_CB(STRUCTTYPE,CB_NAME,FUNC)                                       \
147   Gedcom_ctxt CB_NAME(_REC_PARAMS_)                                           \
148   {                                                                           \
149     struct xref_value* xr = GEDCOM_XREF_PTR(xref);                            \
150     if (! xr->object)                                                         \
151       xr->object = (Gedcom_ctxt) FUNC(xr->string);                            \
152     return (Gedcom_ctxt) MAKE_GOM_CTXT(rec, STRUCTTYPE, xr->object);          \
153   }
154
155 #define GET_REC_BY_XREF(STRUCTTYPE,XREF_TYPE,FUNC_NAME)                       \
156   struct STRUCTTYPE *FUNC_NAME(char *xrefstr)                                 \
157   {                                                                           \
158     struct xref_value* xr = gedcom_get_by_xref(xrefstr);                      \
159     if (xr && (xr->type == XREF_TYPE) && xr->object)                          \
160       return (struct STRUCTTYPE*)(xr->object);                                \
161     else                                                                      \
162       return NULL;                                                            \
163   }
164
165 #define STRING_CB(STRUCTTYPE,CB_NAME,FIELD)                                   \
166   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
167   {                                                                           \
168     char *str = GEDCOM_STRING(parsed_value);                                  \
169     struct STRUCTTYPE *obj                                                    \
170       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
171     if (obj) obj->FIELD = strdup(str);                                        \
172     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
173   }
174
175 #define DATE_CB(STRUCTTYPE,CB_NAME,FIELD)                                     \
176   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
177   {                                                                           \
178     struct date_value dv = GEDCOM_DATE(parsed_value);                         \
179     struct STRUCTTYPE *obj                                                    \
180       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
181     if (obj) obj->FIELD = dup_date(dv);                                       \
182     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
183   }
184
185 #define AGE_CB(STRUCTTYPE,CB_NAME,FIELD)                                      \
186   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
187   {                                                                           \
188     struct age_value age = GEDCOM_AGE(parsed_value);                          \
189     struct STRUCTTYPE *obj                                                    \
190       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
191     if (obj) obj->FIELD = dup_age(age);                                       \
192     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
193   }
194
195 #define XREF_CB(STRUCTTYPE,CB_NAME,FIELD,FUNC)                                \
196   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
197   {                                                                           \
198     struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);                    \
199     struct STRUCTTYPE *obj                                                    \
200       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
201     if (! xr->object)                                                         \
202       xr->object = (Gedcom_ctxt) FUNC(xr->string);                            \
203     if (obj) obj->FIELD = xr;                                                 \
204     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
205   }
206
207 #define XREF_LIST_CB(STRUCTTYPE,CB_NAME,FIELD,FUNC)                           \
208   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
209   {                                                                           \
210     struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);                    \
211     struct STRUCTTYPE *obj                                                    \
212       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
213     struct xref_list *xrl;                                                    \
214     if (! xr->object)                                                         \
215       xr->object = (Gedcom_ctxt) FUNC(xr->string);                            \
216     MAKE_CHAIN_ELT(xref_list, obj->FIELD, xrl);                               \
217     xrl->xref = xr;                                                           \
218     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
219   }
220
221 #define NULL_CB(STRUCTTYPE,CB_NAME)                                           \
222   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
223   {                                                                           \
224     struct STRUCTTYPE *obj                                                    \
225       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
226     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
227   }
228
229 #endif /* __GOM_INTERNAL_H */