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.
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.
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.
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
24 #ifndef __FUNC_TEMPLATE_H
25 #define __FUNC_TEMPLATE_H
27 #define MAKEFUNC(STRUCTTYPE) make_ ## STRUCTTYPE ## _record
28 #define SUB_MAKEFUNC(STRUCTTYPE) make_ ## STRUCTTYPE
29 #define DESTROYFUNC(STRUCTTYPE) destroy_ ## STRUCTTYPE ## _record
30 #define GETXREFFUNC(STRUCTTYPE) gom_get_ ## STRUCTTYPE ## _by_xref
31 #define CLEANFUNC(STRUCTTYPE) STRUCTTYPE ## _cleanup
32 #define ADDFUNC(STRUCTTYPE) gom_add_ ## STRUCTTYPE
33 #define SUB_ADDFUNC(STRUCTTYPE) gom_add_ ## STRUCTTYPE
34 #define DELETEFUNC(STRUCTTYPE) gom_delete_ ## STRUCTTYPE
35 #define SUB_DELETEFUNC(STRUCTTYPE) gom_delete_ ## STRUCTTYPE
36 #define ADDFUNC2(T1,T2) T1 ## _add_ ## T2
37 #define ADDFUNC2_TOVAR(T1,T2,F) T1 ## _add_ ## T2 ## _to_ ## F
38 #define ADDFUNC2_NOLIST(T1,T2) ADDFUNC2(T1,T2)
39 #define ADDFUNC2_STR(T1,F) ADDFUNC2(T1,F)
40 #define ADDFUNC2_STRN(T1,F) ADDFUNC2(T1,F)
42 #define DECLARE_MAKEFUNC(STRUCTTYPE) \
43 struct STRUCTTYPE* MAKEFUNC(STRUCTTYPE)(const char* xref)
45 #define DECLARE_SUB_MAKEFUNC(STRUCTTYPE) \
46 struct STRUCTTYPE* SUB_MAKEFUNC(STRUCTTYPE)()
48 #define DECLARE_CLEANFUNC(STRUCTTYPE) \
49 void CLEANFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj)
51 #define DECLARE_ADDFUNC2(STRUCTTYPE,T2) \
52 void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
54 #define DECLARE_ADDFUNC2_TOVAR(STRUCTTYPE,T2,F) \
55 void ADDFUNC2_TOVAR(STRUCTTYPE,T2,F)(Gom_ctxt ctxt, struct T2* obj)
57 #define DECLARE_ADDFUNC2_NOLIST(STRUCTTYPE,T2) \
58 void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
60 #define DECLARE_ADDFUNC2_STR(STRUCTTYPE,F) \
61 void ADDFUNC2_STR(STRUCTTYPE,F)(Gom_ctxt ctxt, const char* str)
63 #define DECLARE_ADDFUNC2_STRN(STRUCTTYPE,F) \
64 void ADDFUNC2_STRN(STRUCTTYPE,F)(Gom_ctxt ctxt, const char* str)
66 /* Doubly-linked list, but last rec->next is NULL (doesn't go to first rec) */
67 #define LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
69 struct STRUCTTYPE *_local_obj = VAL; \
72 VAL->previous = _local_obj; \
77 (FIRSTVAL)->previous->next = VAL; \
78 VAL->previous = (FIRSTVAL)->previous; \
79 (FIRSTVAL)->previous = VAL; \
83 #define UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
85 struct STRUCTTYPE *_local_obj = VAL; \
86 if (VAL == FIRSTVAL) \
87 FIRSTVAL = _local_obj->next; \
89 VAL->previous->next = VAL->next; \
91 VAL->next->previous = VAL->previous; \
93 (FIRSTVAL)->previous = VAL->previous; \
96 #define MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
98 VAL = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE)); \
102 memset (VAL, 0, sizeof(struct STRUCTTYPE)); \
103 LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
107 #define DESTROY_CHAIN_ELTS(STRUCTTYPE, FIRSTVAL) \
110 struct STRUCTTYPE *runner, *next; \
114 next = runner->next; \
115 CLEANFUNC(STRUCTTYPE)(runner); \
122 /* General functions */
123 #define DEFINE_MAKEFUNC(STRUCTTYPE,FIRSTVAL) \
124 struct STRUCTTYPE* MAKEFUNC(STRUCTTYPE)(const char* xrefstr) { \
125 struct STRUCTTYPE* obj = NULL; \
127 MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj); \
129 obj->xrefstr = strdup(xrefstr); \
130 if (!obj->xrefstr) MEMORY_ERROR; \
136 #define DEFINE_SUB_MAKEFUNC(STRUCTTYPE) \
137 struct STRUCTTYPE* SUB_MAKEFUNC(STRUCTTYPE)() { \
138 struct STRUCTTYPE* obj = NULL; \
139 obj = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE)); \
143 memset(obj, 0, sizeof(struct STRUCTTYPE)); \
147 #define DEFINE_DESTROYFUNC(STRUCTTYPE,FIRSTVAL) \
148 void CLEANFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj); \
149 void DESTROYFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) { \
151 CLEANFUNC(STRUCTTYPE)(obj); \
152 UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj); \
157 #define DEFINE_GETXREFFUNC(STRUCTTYPE,XREF_TYPE) \
158 struct STRUCTTYPE *GETXREFFUNC(STRUCTTYPE)(const char *xrefstr) \
160 struct xref_value* xr = gedcom_get_by_xref(xrefstr); \
161 if (xr && (xr->type == XREF_TYPE) && xr->object) \
162 return (struct STRUCTTYPE*)(xr->object); \
167 #define DEFINE_ADDFUNC(STRUCTTYPE,XREF_TYPE) \
168 struct STRUCTTYPE *ADDFUNC(STRUCTTYPE)(const char* xrefstr) \
170 struct STRUCTTYPE *obj = NULL; \
171 struct xref_value* xrv = gedcom_get_by_xref(xrefstr); \
173 gom_xref_already_in_use(xrefstr); \
175 obj = MAKEFUNC(STRUCTTYPE)(xrefstr); \
177 xrv = gedcom_add_xref(XREF_TYPE, xrefstr, (Gedcom_ctxt)obj); \
179 DESTROYFUNC(STRUCTTYPE)(obj); \
187 #define DEFINE_SUB_ADDFUNC(STRUCTTYPE) \
188 struct STRUCTTYPE *SUB_ADDFUNC(STRUCTTYPE)(struct STRUCTTYPE** addto) \
190 struct STRUCTTYPE *obj = NULL; \
191 if (addto && ! *addto) { \
192 obj = SUB_MAKEFUNC(STRUCTTYPE)(); \
193 if (obj) *addto = obj; \
198 /* TODO: Check whether there are still xrefs linked in */
199 #define DEFINE_DELETEFUNC(STRUCTTYPE) \
200 int DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) \
204 result = gedcom_delete_xref(obj->xrefstr); \
206 DESTROYFUNC(STRUCTTYPE)(obj); \
211 #define DEFINE_SUB_DELETEFUNC(STRUCTTYPE) \
212 int SUB_DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE** obj) \
216 CLEANFUNC(STRUCTTYPE)(*obj); \
223 #define DEFINE_ADDFUNC2(STRUCTTYPE,T2,FIELD) \
224 void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj) \
226 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
228 LINK_CHAIN_ELT(T2, obj->FIELD, addobj); \
231 #define DEFINE_ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD) \
232 void ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD)(Gom_ctxt ctxt, struct T2* addobj) \
234 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
236 LINK_CHAIN_ELT(T2, obj->FIELD, addobj); \
239 #define DEFINE_ADDFUNC2_NOLIST(STRUCTTYPE,T2, FIELD) \
240 void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj) \
242 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
244 obj->FIELD = addobj; \
247 #define DEFINE_ADDFUNC2_STR(STRUCTTYPE,FIELD) \
248 void ADDFUNC2_STR(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str) \
250 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
252 obj->FIELD = strdup(str); \
253 if (! obj->FIELD) MEMORY_ERROR; \
257 #define DEFINE_ADDFUNC2_STRN(STRUCTTYPE,FIELD,N) \
258 void ADDFUNC2_STRN(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str) \
260 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
263 while (i < N-1 && obj->FIELD[i]) i++; \
264 if (! obj->FIELD[i]) { \
265 obj->FIELD[i] = strdup(str); \
266 if (! obj->FIELD[i]) MEMORY_ERROR; \
271 /* Definition of callbacks */
272 #define _REC_PARAMS_ Gedcom_rec rec UNUSED, int level UNUSED, \
273 Gedcom_val xref UNUSED, char *tag UNUSED, \
274 char *raw_value UNUSED, int parsed_tag UNUSED, \
275 Gedcom_val parsed_value UNUSED
277 #define _REC_END_PARAMS_ Gedcom_rec rec UNUSED, Gedcom_ctxt self UNUSED, \
278 Gedcom_val parsed_value UNUSED
280 #define _ELT_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED, \
281 int level UNUSED, char *tag UNUSED, \
282 char *raw_value UNUSED, int parsed_tag UNUSED, \
283 Gedcom_val parsed_value UNUSED
285 #define _ELT_END_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED, \
286 Gedcom_ctxt self UNUSED, \
287 Gedcom_val parsed_value UNUSED
289 #define DEFINE_REC_CB(STRUCTTYPE,CB_NAME) \
290 Gedcom_ctxt CB_NAME(_REC_PARAMS_) \
292 struct xref_value* xr = GEDCOM_XREF_PTR(xref); \
294 xr->object = (Gedcom_ctxt) MAKEFUNC(STRUCTTYPE)(xr->string); \
296 return (Gedcom_ctxt) MAKE_GOM_CTXT(rec, STRUCTTYPE, xr->object); \
301 #define DEFINE_STRING_CB(STRUCTTYPE,CB_NAME,FIELD) \
302 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
304 Gom_ctxt result = NULL; \
308 struct STRUCTTYPE *obj \
309 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
311 char *str = GEDCOM_STRING(parsed_value); \
312 obj->FIELD = strdup(str); \
316 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
319 return (Gedcom_ctxt)result; \
322 #define DEFINE_STRING_END_CB(STRUCTTYPE,CB_NAME,FIELD) \
323 void CB_NAME(_ELT_END_PARAMS_) \
325 Gom_ctxt ctxt = (Gom_ctxt)self; \
329 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
331 char *str = GEDCOM_STRING(parsed_value); \
332 char *newvalue = strdup(str); \
336 obj->FIELD = newvalue; \
338 destroy_gom_ctxt(ctxt); \
342 #define DEFINE_STRING_END_REC_CB(STRUCTTYPE,CB_NAME,FIELD) \
343 void CB_NAME(_REC_END_PARAMS_) \
345 Gom_ctxt ctxt = (Gom_ctxt)self; \
349 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
351 char *str = GEDCOM_STRING(parsed_value); \
352 char *newvalue = strdup(str); \
356 obj->FIELD = newvalue; \
358 destroy_gom_ctxt(ctxt); \
362 #define DEFINE_DATE_CB(STRUCTTYPE,CB_NAME,FIELD) \
363 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
365 Gom_ctxt result = NULL; \
369 struct STRUCTTYPE *obj \
370 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
372 struct date_value dv = GEDCOM_DATE(parsed_value); \
373 obj->FIELD = gedcom_new_date_value(&dv); \
377 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
380 return (Gedcom_ctxt)result; \
383 #define DEFINE_AGE_CB(STRUCTTYPE,CB_NAME,FIELD) \
384 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
386 Gom_ctxt result = NULL; \
390 struct STRUCTTYPE *obj \
391 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
393 struct age_value age = GEDCOM_AGE(parsed_value); \
394 obj->FIELD = gedcom_new_age_value(&age); \
398 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
401 return (Gedcom_ctxt)result; \
404 #define DEFINE_XREF_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE) \
405 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
407 Gom_ctxt result = NULL; \
411 struct STRUCTTYPE *obj \
412 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
413 struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value); \
415 xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string); \
418 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
421 return (Gedcom_ctxt)result; \
424 #define DEFINE_XREF_LIST_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE) \
425 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
427 Gom_ctxt result = NULL; \
431 struct STRUCTTYPE *obj \
432 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
433 struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value); \
434 struct xref_list *xrl; \
436 xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string); \
438 MAKE_CHAIN_ELT(xref_list, obj->FIELD, xrl); \
441 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
445 return (Gedcom_ctxt)result; \
448 #define DEFINE_NULL_CB(STRUCTTYPE,CB_NAME) \
449 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
451 Gom_ctxt result = NULL; \
455 struct STRUCTTYPE *obj \
456 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
458 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
460 return (Gedcom_ctxt)result; \
465 #endif /* __FUNC_TEMPLATE_H */