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 UNREFALLFUNC(STRUCTTYPE) STRUCTTYPE ## _unref_all
35 #define DELETEFUNC(STRUCTTYPE) gom_delete_ ## STRUCTTYPE
36 #define SUB_DELETEFUNC(STRUCTTYPE) gom_delete_ ## STRUCTTYPE
37 #define ADDFUNC2(T1,T2) T1 ## _add_ ## T2
38 #define ADDFUNC2_TOVAR(T1,T2,F) T1 ## _add_ ## T2 ## _to_ ## F
39 #define ADDFUNC2_NOLIST(T1,T2) ADDFUNC2(T1,T2)
40 #define ADDFUNC2_STR(T1,F) ADDFUNC2(T1,F)
41 #define ADDFUNC2_STRN(T1,F) ADDFUNC2(T1,F)
43 #define DECLARE_MAKEFUNC(STRUCTTYPE) \
44 struct STRUCTTYPE* MAKEFUNC(STRUCTTYPE)(const char* xref)
46 #define DECLARE_SUB_MAKEFUNC(STRUCTTYPE) \
47 struct STRUCTTYPE* SUB_MAKEFUNC(STRUCTTYPE)()
49 #define DECLARE_CLEANFUNC(STRUCTTYPE) \
50 void CLEANFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj)
52 #define DECLARE_UNREFALLFUNC(STRUCTTYPE) \
53 void UNREFALLFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj)
55 #define DECLARE_ADDFUNC2(STRUCTTYPE,T2) \
56 void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
58 #define DECLARE_ADDFUNC2_TOVAR(STRUCTTYPE,T2,F) \
59 void ADDFUNC2_TOVAR(STRUCTTYPE,T2,F)(Gom_ctxt ctxt, struct T2* obj)
61 #define DECLARE_ADDFUNC2_NOLIST(STRUCTTYPE,T2) \
62 void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
64 #define DECLARE_ADDFUNC2_STR(STRUCTTYPE,F) \
65 void ADDFUNC2_STR(STRUCTTYPE,F)(Gom_ctxt ctxt, const char* str)
67 #define DECLARE_ADDFUNC2_STRN(STRUCTTYPE,F) \
68 void ADDFUNC2_STRN(STRUCTTYPE,F)(Gom_ctxt ctxt, const char* str)
70 /* Doubly-linked list, but last rec->next is NULL (doesn't go to first rec) */
71 #define LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
73 struct STRUCTTYPE *_local_obj = VAL; \
76 VAL->previous = _local_obj; \
81 (FIRSTVAL)->previous->next = VAL; \
82 VAL->previous = (FIRSTVAL)->previous; \
83 (FIRSTVAL)->previous = VAL; \
87 #define UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
89 struct STRUCTTYPE *_local_obj = VAL; \
90 if (VAL == FIRSTVAL) \
91 FIRSTVAL = _local_obj->next; \
93 VAL->previous->next = VAL->next; \
95 VAL->next->previous = VAL->previous; \
97 (FIRSTVAL)->previous = VAL->previous; \
100 #define MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
102 VAL = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE)); \
106 memset (VAL, 0, sizeof(struct STRUCTTYPE)); \
107 LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
111 #define DESTROY_CHAIN_ELTS(STRUCTTYPE, FIRSTVAL) \
114 struct STRUCTTYPE *runner, *next; \
118 next = runner->next; \
119 CLEANFUNC(STRUCTTYPE)(runner); \
126 /* General functions */
127 #define DEFINE_MAKEFUNC(STRUCTTYPE,FIRSTVAL) \
128 struct STRUCTTYPE* MAKEFUNC(STRUCTTYPE)(const char* xrefstr) { \
129 struct STRUCTTYPE* obj = NULL; \
131 MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj); \
133 obj->xrefstr = strdup(xrefstr); \
134 if (!obj->xrefstr) MEMORY_ERROR; \
140 #define DEFINE_SUB_MAKEFUNC(STRUCTTYPE) \
141 struct STRUCTTYPE* SUB_MAKEFUNC(STRUCTTYPE)() { \
142 struct STRUCTTYPE* obj = NULL; \
143 obj = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE)); \
147 memset(obj, 0, sizeof(struct STRUCTTYPE)); \
151 #define DEFINE_DESTROYFUNC(STRUCTTYPE,FIRSTVAL) \
152 DECLARE_CLEANFUNC(STRUCTTYPE); \
153 void DESTROYFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) { \
155 CLEANFUNC(STRUCTTYPE)(obj); \
156 UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj); \
161 #define DEFINE_GETXREFFUNC(STRUCTTYPE,XREF_TYPE) \
162 struct STRUCTTYPE *GETXREFFUNC(STRUCTTYPE)(const char *xrefstr) \
164 struct xref_value* xr = gedcom_get_by_xref(xrefstr); \
165 if (xr && (xr->type == XREF_TYPE) && xr->object) \
166 return (struct STRUCTTYPE*)(xr->object); \
171 #define DEFINE_ADDFUNC(STRUCTTYPE,XREF_TYPE) \
172 struct STRUCTTYPE *ADDFUNC(STRUCTTYPE)(const char* xrefstr) \
174 struct STRUCTTYPE *obj = NULL; \
175 struct xref_value* xrv = gedcom_get_by_xref(xrefstr); \
177 gom_xref_already_in_use(xrefstr); \
179 obj = MAKEFUNC(STRUCTTYPE)(xrefstr); \
181 xrv = gedcom_add_xref(XREF_TYPE, xrefstr, (Gedcom_ctxt)obj); \
183 DESTROYFUNC(STRUCTTYPE)(obj); \
191 #define DEFINE_SUB_ADDFUNC(STRUCTTYPE) \
192 struct STRUCTTYPE *SUB_ADDFUNC(STRUCTTYPE)(struct STRUCTTYPE** addto) \
194 struct STRUCTTYPE *obj = NULL; \
195 if (addto && ! *addto) { \
196 obj = SUB_MAKEFUNC(STRUCTTYPE)(); \
197 if (obj) *addto = obj; \
202 #define DEFINE_DELETEFUNC(STRUCTTYPE) \
203 DECLARE_UNREFALLFUNC(STRUCTTYPE); \
204 int DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) \
208 result = gedcom_delete_xref(obj->xrefstr); \
210 UNREFALLFUNC(STRUCTTYPE)(obj); \
211 DESTROYFUNC(STRUCTTYPE)(obj); \
217 #define DEFINE_SUB_DELETEFUNC(STRUCTTYPE) \
218 int SUB_DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE** obj) \
222 UNREFALLFUNC(STRUCTTYPE)(*obj); \
223 CLEANFUNC(STRUCTTYPE)(*obj); \
230 #define DEFINE_ADDFUNC2(STRUCTTYPE,T2,FIELD) \
231 void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj) \
233 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
235 LINK_CHAIN_ELT(T2, obj->FIELD, addobj); \
238 #define DEFINE_ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD) \
239 void ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD)(Gom_ctxt ctxt, struct T2* addobj) \
241 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
243 LINK_CHAIN_ELT(T2, obj->FIELD, addobj); \
246 #define DEFINE_ADDFUNC2_NOLIST(STRUCTTYPE,T2, FIELD) \
247 void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj) \
249 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
251 obj->FIELD = addobj; \
254 #define DEFINE_ADDFUNC2_STR(STRUCTTYPE,FIELD) \
255 void ADDFUNC2_STR(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str) \
257 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
259 obj->FIELD = strdup(str); \
260 if (! obj->FIELD) MEMORY_ERROR; \
264 #define DEFINE_ADDFUNC2_STRN(STRUCTTYPE,FIELD,N) \
265 void ADDFUNC2_STRN(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str) \
267 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
270 while (i < N-1 && obj->FIELD[i]) i++; \
271 if (! obj->FIELD[i]) { \
272 obj->FIELD[i] = strdup(str); \
273 if (! obj->FIELD[i]) MEMORY_ERROR; \
278 /* Definition of callbacks */
279 #define _REC_PARAMS_ Gedcom_rec rec UNUSED, int level UNUSED, \
280 Gedcom_val xref UNUSED, char *tag UNUSED, \
281 char *raw_value UNUSED, int parsed_tag UNUSED, \
282 Gedcom_val parsed_value UNUSED
284 #define _REC_END_PARAMS_ Gedcom_rec rec UNUSED, Gedcom_ctxt self UNUSED, \
285 Gedcom_val parsed_value UNUSED
287 #define _ELT_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED, \
288 int level UNUSED, char *tag UNUSED, \
289 char *raw_value UNUSED, int parsed_tag UNUSED, \
290 Gedcom_val parsed_value UNUSED
292 #define _ELT_END_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED, \
293 Gedcom_ctxt self UNUSED, \
294 Gedcom_val parsed_value UNUSED
296 #define DEFINE_REC_CB(STRUCTTYPE,CB_NAME) \
297 Gedcom_ctxt CB_NAME(_REC_PARAMS_) \
299 struct xref_value* xr = GEDCOM_XREF_PTR(xref); \
301 xr->object = (Gedcom_ctxt) MAKEFUNC(STRUCTTYPE)(xr->string); \
303 return (Gedcom_ctxt) MAKE_GOM_CTXT(rec, STRUCTTYPE, xr->object); \
308 #define DEFINE_STRING_CB(STRUCTTYPE,CB_NAME,FIELD) \
309 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
311 Gom_ctxt result = NULL; \
315 struct STRUCTTYPE *obj \
316 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
318 char *str = GEDCOM_STRING(parsed_value); \
319 obj->FIELD = strdup(str); \
323 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
326 return (Gedcom_ctxt)result; \
329 #define DEFINE_STRING_END_CB(STRUCTTYPE,CB_NAME,FIELD) \
330 void CB_NAME(_ELT_END_PARAMS_) \
332 Gom_ctxt ctxt = (Gom_ctxt)self; \
336 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
338 char *str = GEDCOM_STRING(parsed_value); \
339 char *newvalue = strdup(str); \
343 obj->FIELD = newvalue; \
345 destroy_gom_ctxt(ctxt); \
349 #define DEFINE_STRING_END_REC_CB(STRUCTTYPE,CB_NAME,FIELD) \
350 void CB_NAME(_REC_END_PARAMS_) \
352 Gom_ctxt ctxt = (Gom_ctxt)self; \
356 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
358 char *str = GEDCOM_STRING(parsed_value); \
359 char *newvalue = strdup(str); \
363 obj->FIELD = newvalue; \
365 destroy_gom_ctxt(ctxt); \
369 #define DEFINE_DATE_CB(STRUCTTYPE,CB_NAME,FIELD) \
370 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
372 Gom_ctxt result = NULL; \
376 struct STRUCTTYPE *obj \
377 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
379 struct date_value dv = GEDCOM_DATE(parsed_value); \
380 obj->FIELD = gedcom_new_date_value(&dv); \
384 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
387 return (Gedcom_ctxt)result; \
390 #define DEFINE_AGE_CB(STRUCTTYPE,CB_NAME,FIELD) \
391 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
393 Gom_ctxt result = NULL; \
397 struct STRUCTTYPE *obj \
398 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
400 struct age_value age = GEDCOM_AGE(parsed_value); \
401 obj->FIELD = gedcom_new_age_value(&age); \
405 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
408 return (Gedcom_ctxt)result; \
411 #define DEFINE_XREF_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE) \
412 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
414 Gom_ctxt result = NULL; \
418 struct STRUCTTYPE *obj \
419 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
420 struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value); \
422 xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string); \
425 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
428 return (Gedcom_ctxt)result; \
431 #define DEFINE_XREF_LIST_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE) \
432 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
434 Gom_ctxt result = NULL; \
438 struct STRUCTTYPE *obj \
439 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
440 struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value); \
441 struct xref_list *xrl; \
443 xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string); \
445 MAKE_CHAIN_ELT(xref_list, obj->FIELD, xrl); \
448 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
452 return (Gedcom_ctxt)result; \
455 #define DEFINE_NULL_CB(STRUCTTYPE,CB_NAME) \
456 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
458 Gom_ctxt result = NULL; \
462 struct STRUCTTYPE *obj \
463 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
465 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
467 return (Gedcom_ctxt)result; \
472 #endif /* __FUNC_TEMPLATE_H */