Moved update_date and update_time to change_date.c
[gedcom-parse.git] / gom / func_template.h
1 /* General header for the Gedcom object model, defining function macros
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 __FUNC_TEMPLATE_H
25 #define __FUNC_TEMPLATE_H
26
27 #define MAKEFUNC(STRUCTTYPE)     make_ ## STRUCTTYPE ## _record
28 #define DESTROYFUNC(STRUCTTYPE)  destroy_ ## STRUCTTYPE ## _record
29 #define GETXREFFUNC(STRUCTTYPE)  gom_get_ ## STRUCTTYPE ## _by_xref
30 #define CLEANFUNC(STRUCTTYPE)    STRUCTTYPE ## _cleanup
31 #define ADDFUNC(STRUCTTYPE)      gom_add_ ## STRUCTTYPE
32 #define DELETEFUNC(STRUCTTYPE)   gom_delete_ ## STRUCTTYPE
33 #define ADDFUNC2(T1,T2)          T1 ## _add_ ## T2
34 #define ADDFUNC2_TOVAR(T1,T2,F)  T1 ## _add_ ## T2 ## _to_ ## F
35 #define ADDFUNC2_NOLIST(T1,T2)   ADDFUNC2(T1,T2)
36 #define ADDFUNC2_STR(T1,F)       ADDFUNC2(T1,F)
37 #define ADDFUNC2_STRN(T1,F)      ADDFUNC2(T1,F)
38
39 #define DECLARE_MAKEFUNC(STRUCTTYPE)                                          \
40   struct STRUCTTYPE* MAKEFUNC(STRUCTTYPE)(const char* xref)
41
42 #define DECLARE_CLEANFUNC(STRUCTTYPE)                                         \
43   void CLEANFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj)
44
45 #define DECLARE_ADDFUNC2(STRUCTTYPE,T2)                                       \
46   void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
47
48 #define DECLARE_ADDFUNC2_TOVAR(STRUCTTYPE,T2,F)                               \
49   void ADDFUNC2_TOVAR(STRUCTTYPE,T2,F)(Gom_ctxt ctxt, struct T2* obj)
50
51 #define DECLARE_ADDFUNC2_NOLIST(STRUCTTYPE,T2)                                \
52   void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
53
54 #define DECLARE_ADDFUNC2_STR(STRUCTTYPE,F)                                    \
55   void ADDFUNC2_STR(STRUCTTYPE,F)(Gom_ctxt ctxt, const char* str)
56
57 #define DECLARE_ADDFUNC2_STRN(STRUCTTYPE,F)                                   \
58   void ADDFUNC2_STRN(STRUCTTYPE,F)(Gom_ctxt ctxt, const char* str)
59
60 /* Doubly-linked list, but last rec->next is NULL (doesn't go to first rec) */
61 #define LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                             \
62   {                                                                           \
63     struct STRUCTTYPE *_local_obj = VAL;                                      \
64     if (! FIRSTVAL) {                                                         \
65       VAL->next = NULL;                                                       \
66       VAL->previous = _local_obj;                                             \
67       FIRSTVAL = VAL;                                                         \
68     }                                                                         \
69     else {                                                                    \
70       VAL->next = NULL;                                                       \
71       FIRSTVAL->previous->next = VAL;                                         \
72       VAL->previous = FIRSTVAL->previous;                                     \
73       FIRSTVAL->previous = VAL;                                               \
74     }                                                                         \
75   }
76
77 #define UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                           \
78   {                                                                           \
79     struct STRUCTTYPE *_local_obj = VAL;                                      \
80     if (VAL == FIRSTVAL)                                                      \
81       FIRSTVAL = _local_obj->next;                                            \
82     else                                                                      \
83       VAL->previous->next = VAL->next;                                        \
84     if (VAL->next)                                                            \
85       VAL->next->previous = VAL->previous;                                    \
86   }
87
88 #define MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                             \
89   {                                                                           \
90     VAL = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE));             \
91     if (! VAL)                                                                \
92       MEMORY_ERROR;                                                           \
93     else {                                                                    \
94       memset (VAL, 0, sizeof(struct STRUCTTYPE));                             \
95       LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                               \
96     }                                                                         \
97   }
98
99 #define DESTROY_CHAIN_ELTS(STRUCTTYPE, FIRSTVAL)                              \
100   {                                                                           \
101     if (FIRSTVAL) {                                                           \
102       struct STRUCTTYPE *runner, *next;                                       \
103       runner = FIRSTVAL;                                                      \
104       while (runner) {                                                        \
105         next = runner->next;                                                  \
106         CLEANFUNC(STRUCTTYPE)(runner);                                        \
107         SAFE_FREE(runner);                                                    \
108         runner = next;                                                        \
109       }                                                                       \
110     }                                                                         \
111   }
112
113 /* General functions */
114 #define DEFINE_MAKEFUNC(STRUCTTYPE,FIRSTVAL)                                  \
115   struct STRUCTTYPE* MAKEFUNC(STRUCTTYPE)(const char* xrefstr) {              \
116     struct STRUCTTYPE* obj = NULL;                                            \
117     if (xrefstr) {                                                            \
118       MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj);                              \
119       if (obj) {                                                              \
120         obj->xrefstr = strdup(xrefstr);                                       \
121         if (!obj->xrefstr) MEMORY_ERROR;                                      \
122       }                                                                       \
123     }                                                                         \
124     return obj;                                                               \
125   }
126
127 #define DEFINE_DESTROYFUNC(STRUCTTYPE,FIRSTVAL)                               \
128   void CLEANFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj);                         \
129   void DESTROYFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) {                      \
130     if (obj) {                                                                \
131       CLEANFUNC(STRUCTTYPE)(obj);                                             \
132       UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj);                            \
133       free(obj);                                                              \
134     }                                                                         \
135   }
136
137 #define DEFINE_GETXREFFUNC(STRUCTTYPE,XREF_TYPE)                              \
138   struct STRUCTTYPE *GETXREFFUNC(STRUCTTYPE)(const char *xrefstr)             \
139   {                                                                           \
140     struct xref_value* xr = gedcom_get_by_xref(xrefstr);                      \
141     if (xr && (xr->type == XREF_TYPE) && xr->object)                          \
142       return (struct STRUCTTYPE*)(xr->object);                                \
143     else                                                                      \
144       return NULL;                                                            \
145   }
146
147 #define DEFINE_ADDFUNC(STRUCTTYPE,XREF_TYPE)                                  \
148   struct STRUCTTYPE *ADDFUNC(STRUCTTYPE)(const char* xrefstr)                 \
149   {                                                                           \
150     struct STRUCTTYPE *obj = NULL;                                            \
151     struct xref_value* xrv = gedcom_get_by_xref(xrefstr);                     \
152     if (xrv)                                                                  \
153       gom_xref_already_in_use(xrefstr);                                       \
154     else {                                                                    \
155       obj = MAKEFUNC(STRUCTTYPE)(xrefstr);                                    \
156       if (obj) {                                                              \
157         xrv = gedcom_add_xref(XREF_TYPE, xrefstr, (Gedcom_ctxt)obj);          \
158         if (!xrv) {                                                           \
159           DESTROYFUNC(STRUCTTYPE)(obj);                                       \
160           obj = NULL;                                                         \
161         }                                                                     \
162       }                                                                       \
163     }                                                                         \
164     return obj;                                                               \
165   }
166
167 #define DEFINE_DELETEFUNC(STRUCTTYPE)                                         \
168   int DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj)                          \
169   {                                                                           \
170     int result = 1;                                                           \
171     if (obj) {                                                                \
172       result = gedcom_delete_xref(obj->xrefstr);                              \
173       if (result == 0)                                                        \
174         DESTROYFUNC(STRUCTTYPE)(obj);                                         \
175     }                                                                         \
176     return result;                                                            \
177   }
178
179 #define DEFINE_ADDFUNC2(STRUCTTYPE,T2,FIELD)                                  \
180   void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj)              \
181   {                                                                           \
182     struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt);                \
183     if (obj)                                                                  \
184       LINK_CHAIN_ELT(T2, obj->FIELD, addobj);                                 \
185   }
186
187 #define DEFINE_ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD)                            \
188   void ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD)(Gom_ctxt ctxt, struct T2* addobj)  \
189   {                                                                           \
190     struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt);                \
191     if (obj)                                                                  \
192       LINK_CHAIN_ELT(T2, obj->FIELD, addobj);                                 \
193   }
194
195 #define DEFINE_ADDFUNC2_NOLIST(STRUCTTYPE,T2, FIELD)                          \
196   void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj)       \
197   {                                                                           \
198     struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt);                \
199     if (obj)                                                                  \
200       obj->FIELD = addobj;                                                    \
201   }
202
203 #define DEFINE_ADDFUNC2_STR(STRUCTTYPE,FIELD)                                 \
204 void ADDFUNC2_STR(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str)           \
205 {                                                                             \
206   struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt);                  \
207   if (obj) {                                                                  \
208     obj->FIELD = strdup(str);                                                 \
209     if (! obj->FIELD) MEMORY_ERROR;                                           \
210   }                                                                           \
211 }
212
213 #define DEFINE_ADDFUNC2_STRN(STRUCTTYPE,FIELD,N)                              \
214 void ADDFUNC2_STRN(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str)          \
215 {                                                                             \
216   struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt);                  \
217   if (obj) {                                                                  \
218     int i = 0;                                                                \
219     while (i < N-1 && obj->FIELD[i]) i++;                                     \
220     if (! obj->FIELD[i]) {                                                    \
221       obj->FIELD[i] = strdup(str);                                            \
222       if (! obj->FIELD[i]) MEMORY_ERROR;                                      \
223     }                                                                         \
224   }                                                                           \
225 }
226
227 /* Definition of callbacks */
228 #define _REC_PARAMS_ Gedcom_rec rec UNUSED, int level UNUSED,                 \
229                      Gedcom_val xref UNUSED, char *tag UNUSED,                \
230                      char *raw_value UNUSED, int parsed_tag UNUSED,           \
231                      Gedcom_val parsed_value UNUSED
232
233 #define _REC_END_PARAMS_ Gedcom_rec rec UNUSED, Gedcom_ctxt self UNUSED,      \
234                          Gedcom_val parsed_value UNUSED
235
236 #define _ELT_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED,        \
237                      int level UNUSED, char *tag UNUSED,                      \
238                      char *raw_value UNUSED, int parsed_tag UNUSED,           \
239                      Gedcom_val parsed_value UNUSED
240
241 #define _ELT_END_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED,    \
242                          Gedcom_ctxt self UNUSED,                             \
243                          Gedcom_val parsed_value UNUSED
244
245 #define DEFINE_REC_CB(STRUCTTYPE,CB_NAME)                                     \
246   Gedcom_ctxt CB_NAME(_REC_PARAMS_)                                           \
247   {                                                                           \
248     struct xref_value* xr = GEDCOM_XREF_PTR(xref);                            \
249     if (! xr->object)                                                         \
250       xr->object = (Gedcom_ctxt) MAKEFUNC(STRUCTTYPE)(xr->string);            \
251     if (xr->object)                                                           \
252       return (Gedcom_ctxt) MAKE_GOM_CTXT(rec, STRUCTTYPE, xr->object);        \
253     else                                                                      \
254       return NULL;                                                            \
255   }
256
257 #define DEFINE_STRING_CB(STRUCTTYPE,CB_NAME,FIELD)                            \
258   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
259   {                                                                           \
260     Gom_ctxt result = NULL;                                                   \
261     if (! parent)                                                             \
262       NO_CONTEXT;                                                             \
263     else {                                                                    \
264       struct STRUCTTYPE *obj                                                  \
265         = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
266       if (obj) {                                                              \
267         char *str = GEDCOM_STRING(parsed_value);                              \
268         obj->FIELD = strdup(str);                                             \
269         if (! obj->FIELD)                                                     \
270           MEMORY_ERROR;                                                       \
271         else                                                                  \
272           result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                       \
273       }                                                                       \
274     }                                                                         \
275     return (Gedcom_ctxt)result;                                               \
276   }
277
278 #define DEFINE_STRING_END_CB(STRUCTTYPE,CB_NAME,FIELD)                        \
279   void CB_NAME(_ELT_END_PARAMS_)                                              \
280   {                                                                           \
281     Gom_ctxt ctxt = (Gom_ctxt)self;                                           \
282     if (! ctxt)                                                               \
283       NO_CONTEXT;                                                             \
284     else {                                                                    \
285       struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt);              \
286       if (obj) {                                                              \
287         char *str = GEDCOM_STRING(parsed_value);                              \
288         char *newvalue = strdup(str);                                         \
289         if (! newvalue)                                                       \
290           MEMORY_ERROR;                                                       \
291         else                                                                  \
292           obj->FIELD = newvalue;                                              \
293       }                                                                       \
294       destroy_gom_ctxt(ctxt);                                                 \
295     }                                                                         \
296   }
297
298 #define DEFINE_STRING_END_REC_CB(STRUCTTYPE,CB_NAME,FIELD)                    \
299   void CB_NAME(_REC_END_PARAMS_)                                              \
300   {                                                                           \
301     Gom_ctxt ctxt = (Gom_ctxt)self;                                           \
302     if (! ctxt)                                                               \
303       NO_CONTEXT;                                                             \
304     else {                                                                    \
305       struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt);              \
306       if (obj) {                                                              \
307         char *str = GEDCOM_STRING(parsed_value);                              \
308         char *newvalue = strdup(str);                                         \
309         if (! newvalue)                                                       \
310           MEMORY_ERROR;                                                       \
311         else                                                                  \
312           obj->FIELD = newvalue;                                              \
313       }                                                                       \
314       destroy_gom_ctxt(ctxt);                                                 \
315     }                                                                         \
316   }
317
318 #define DEFINE_DATE_CB(STRUCTTYPE,CB_NAME,FIELD)                              \
319   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
320   {                                                                           \
321     Gom_ctxt result = NULL;                                                   \
322     if (! parent)                                                             \
323       NO_CONTEXT;                                                             \
324     else {                                                                    \
325       struct STRUCTTYPE *obj                                                  \
326         = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
327       if (obj) {                                                              \
328         struct date_value dv = GEDCOM_DATE(parsed_value);                     \
329         obj->FIELD = gedcom_new_date_value(&dv);                              \
330         if (! obj->FIELD)                                                     \
331           MEMORY_ERROR;                                                       \
332         else                                                                  \
333           result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                       \
334       }                                                                       \
335     }                                                                         \
336     return (Gedcom_ctxt)result;                                               \
337   }
338
339 #define DEFINE_AGE_CB(STRUCTTYPE,CB_NAME,FIELD)                               \
340   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
341   {                                                                           \
342     Gom_ctxt result = NULL;                                                   \
343     if (! parent)                                                             \
344       NO_CONTEXT;                                                             \
345     else {                                                                    \
346       struct STRUCTTYPE *obj                                                  \
347         = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
348       if (obj) {                                                              \
349         struct age_value age = GEDCOM_AGE(parsed_value);                      \
350         obj->FIELD = gedcom_new_age_value(&age);                              \
351         if (! obj->FIELD)                                                     \
352           MEMORY_ERROR;                                                       \
353         else                                                                  \
354           result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                       \
355       }                                                                       \
356     }                                                                         \
357     return (Gedcom_ctxt)result;                                               \
358   }
359
360 #define DEFINE_XREF_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE)                  \
361   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
362   {                                                                           \
363     Gom_ctxt result = NULL;                                                   \
364     if (! parent)                                                             \
365       NO_CONTEXT;                                                             \
366     else {                                                                    \
367       struct STRUCTTYPE *obj                                                  \
368         = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
369       struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);                  \
370       if (! xr->object)                                                       \
371         xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string);         \
372       if (obj) {                                                              \
373         obj->FIELD = xr;                                                      \
374         result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                         \
375       }                                                                       \
376     }                                                                         \
377     return (Gedcom_ctxt)result;                                               \
378   }
379
380 #define DEFINE_XREF_LIST_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE)             \
381   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
382   {                                                                           \
383     Gom_ctxt result = NULL;                                                   \
384     if (! parent)                                                             \
385       NO_CONTEXT;                                                             \
386     else {                                                                    \
387       struct STRUCTTYPE *obj                                                  \
388         = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
389       struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);                  \
390       struct xref_list *xrl;                                                  \
391       if (! xr->object)                                                       \
392         xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string);         \
393       if (obj) {                                                              \
394         MAKE_CHAIN_ELT(xref_list, obj->FIELD, xrl);                           \
395         if (xrl) {                                                            \
396           xrl->xref = xr;                                                     \
397           result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                       \
398         }                                                                     \
399       }                                                                       \
400     }                                                                         \
401     return (Gedcom_ctxt)result;                                               \
402   }
403
404 #define DEFINE_NULL_CB(STRUCTTYPE,CB_NAME)                                    \
405   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
406   {                                                                           \
407     Gom_ctxt result = NULL;                                                   \
408     if (! parent)                                                             \
409       NO_CONTEXT;                                                             \
410     else {                                                                    \
411       struct STRUCTTYPE *obj                                                  \
412         = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
413       if (obj)                                                                \
414         result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                         \
415     }                                                                         \
416     return (Gedcom_ctxt)result;                                               \
417   }
418
419
420
421 #endif /* __FUNC_TEMPLATE_H */