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_new_ ## STRUCTTYPE
33 #define SUB_SETFUNC(STRUCTTYPE) gom_set_new_ ## 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 MOVE_CHAIN_ELT(STRUCTTYPE, DIR, FIRSTVAL, VAL) \
102 struct STRUCTTYPE *first, *second; \
103 if (DIR == MOVE_UP) { \
104 first = VAL->previous; \
109 second = VAL->next; \
111 if (second && (second != FIRSTVAL)) { \
112 if (first != FIRSTVAL) \
113 first->previous->next = second; \
118 second->next->previous = first; \
120 (FIRSTVAL)->previous = first; \
122 first->next = second->next; \
123 second->next = first; \
125 second->previous = first->previous; \
126 first->previous = second; \
129 gom_move_error(#STRUCTTYPE); \
133 #define MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
135 VAL = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE)); \
139 memset (VAL, 0, sizeof(struct STRUCTTYPE)); \
140 LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
144 #define DESTROY_CHAIN_ELTS(STRUCTTYPE, FIRSTVAL) \
147 struct STRUCTTYPE *runner, *next; \
151 next = runner->next; \
152 CLEANFUNC(STRUCTTYPE)(runner); \
159 /* General functions */
160 #define DEFINE_MAKEFUNC(STRUCTTYPE,FIRSTVAL) \
161 struct STRUCTTYPE* MAKEFUNC(STRUCTTYPE)(const char* xrefstr) { \
162 struct STRUCTTYPE* obj = NULL; \
164 MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj); \
166 obj->xrefstr = strdup(xrefstr); \
167 if (!obj->xrefstr) MEMORY_ERROR; \
173 #define DEFINE_SUB_MAKEFUNC(STRUCTTYPE) \
174 struct STRUCTTYPE* SUB_MAKEFUNC(STRUCTTYPE)() { \
175 struct STRUCTTYPE* obj = NULL; \
176 obj = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE)); \
180 memset(obj, 0, sizeof(struct STRUCTTYPE)); \
184 #define DEFINE_DESTROYFUNC(STRUCTTYPE,FIRSTVAL) \
185 DECLARE_CLEANFUNC(STRUCTTYPE); \
186 void DESTROYFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) { \
188 CLEANFUNC(STRUCTTYPE)(obj); \
189 UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj); \
194 #define DEFINE_GETXREFFUNC(STRUCTTYPE,XREF_TYPE) \
195 struct STRUCTTYPE *GETXREFFUNC(STRUCTTYPE)(const char *xrefstr) \
197 struct xref_value* xr = gedcom_get_by_xref(xrefstr); \
198 if (xr && (xr->type == XREF_TYPE) && xr->object) \
199 return (struct STRUCTTYPE*)(xr->object); \
204 #define DEFINE_ADDFUNC(STRUCTTYPE,XREF_TYPE) \
205 struct STRUCTTYPE *ADDFUNC(STRUCTTYPE)(const char* xrefstr) \
207 struct STRUCTTYPE *obj = NULL; \
208 struct xref_value* xrv = gedcom_get_by_xref(xrefstr); \
210 gom_xref_already_in_use(xrefstr); \
212 obj = MAKEFUNC(STRUCTTYPE)(xrefstr); \
214 xrv = gedcom_add_xref(XREF_TYPE, xrefstr, (Gedcom_ctxt)obj); \
216 DESTROYFUNC(STRUCTTYPE)(obj); \
224 #define DEFINE_SUB_SETFUNC(STRUCTTYPE) \
225 struct STRUCTTYPE *SUB_SETFUNC(STRUCTTYPE)(struct STRUCTTYPE** addto) \
227 struct STRUCTTYPE *obj = NULL; \
228 if (addto && ! *addto) { \
229 obj = SUB_MAKEFUNC(STRUCTTYPE)(); \
230 if (obj) *addto = obj; \
235 #define DEFINE_DELETEFUNC(STRUCTTYPE) \
236 DECLARE_UNREFALLFUNC(STRUCTTYPE); \
237 int DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) \
241 result = gedcom_delete_xref(obj->xrefstr); \
243 UNREFALLFUNC(STRUCTTYPE)(obj); \
244 DESTROYFUNC(STRUCTTYPE)(obj); \
250 #define DEFINE_SUB_DELETEFUNC(STRUCTTYPE) \
251 int SUB_DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE** obj) \
255 UNREFALLFUNC(STRUCTTYPE)(*obj); \
256 CLEANFUNC(STRUCTTYPE)(*obj); \
263 #define DEFINE_ADDFUNC2(STRUCTTYPE,T2,FIELD) \
264 void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj) \
266 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
268 LINK_CHAIN_ELT(T2, obj->FIELD, addobj); \
271 #define DEFINE_ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD) \
272 void ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD)(Gom_ctxt ctxt, struct T2* addobj) \
274 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
276 LINK_CHAIN_ELT(T2, obj->FIELD, addobj); \
279 #define DEFINE_ADDFUNC2_NOLIST(STRUCTTYPE,T2, FIELD) \
280 void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj) \
282 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
284 obj->FIELD = addobj; \
287 #define DEFINE_ADDFUNC2_STR(STRUCTTYPE,FIELD) \
288 void ADDFUNC2_STR(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str) \
290 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
292 obj->FIELD = strdup(str); \
293 if (! obj->FIELD) MEMORY_ERROR; \
297 #define DEFINE_ADDFUNC2_STRN(STRUCTTYPE,FIELD,N) \
298 void ADDFUNC2_STRN(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str) \
300 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
303 while (i < N-1 && obj->FIELD[i]) i++; \
304 if (! obj->FIELD[i]) { \
305 obj->FIELD[i] = strdup(str); \
306 if (! obj->FIELD[i]) MEMORY_ERROR; \
311 /* Definition of callbacks */
312 #define _REC_PARAMS_ Gedcom_rec rec UNUSED, int level UNUSED, \
313 Gedcom_val xref UNUSED, char *tag UNUSED, \
314 char *raw_value UNUSED, int parsed_tag UNUSED, \
315 Gedcom_val parsed_value UNUSED
317 #define _REC_END_PARAMS_ Gedcom_rec rec UNUSED, Gedcom_ctxt self UNUSED, \
318 Gedcom_val parsed_value UNUSED
320 #define _ELT_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED, \
321 int level UNUSED, char *tag UNUSED, \
322 char *raw_value UNUSED, int parsed_tag UNUSED, \
323 Gedcom_val parsed_value UNUSED
325 #define _ELT_END_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED, \
326 Gedcom_ctxt self UNUSED, \
327 Gedcom_val parsed_value UNUSED
329 #define DEFINE_REC_CB(STRUCTTYPE,CB_NAME) \
330 Gedcom_ctxt CB_NAME(_REC_PARAMS_) \
332 struct xref_value* xr = GEDCOM_XREF_PTR(xref); \
334 xr->object = (Gedcom_ctxt) MAKEFUNC(STRUCTTYPE)(xr->string); \
336 return (Gedcom_ctxt) MAKE_GOM_CTXT(rec, STRUCTTYPE, xr->object); \
341 #define DEFINE_STRING_CB(STRUCTTYPE,CB_NAME,FIELD) \
342 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
344 Gom_ctxt result = NULL; \
348 struct STRUCTTYPE *obj \
349 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
351 char *str = GEDCOM_STRING(parsed_value); \
352 obj->FIELD = strdup(str); \
356 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
359 return (Gedcom_ctxt)result; \
362 #define DEFINE_STRING_END_CB(STRUCTTYPE,CB_NAME,FIELD) \
363 void CB_NAME(_ELT_END_PARAMS_) \
365 Gom_ctxt ctxt = (Gom_ctxt)self; \
369 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
371 char *str = GEDCOM_STRING(parsed_value); \
372 char *newvalue = strdup(str); \
376 obj->FIELD = newvalue; \
378 destroy_gom_ctxt(ctxt); \
382 #define DEFINE_STRING_END_REC_CB(STRUCTTYPE,CB_NAME,FIELD) \
383 void CB_NAME(_REC_END_PARAMS_) \
385 Gom_ctxt ctxt = (Gom_ctxt)self; \
389 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
391 char *str = GEDCOM_STRING(parsed_value); \
392 char *newvalue = strdup(str); \
396 obj->FIELD = newvalue; \
398 destroy_gom_ctxt(ctxt); \
402 #define DEFINE_DATE_CB(STRUCTTYPE,CB_NAME,FIELD) \
403 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
405 Gom_ctxt result = NULL; \
409 struct STRUCTTYPE *obj \
410 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
412 struct date_value dv = GEDCOM_DATE(parsed_value); \
413 obj->FIELD = gedcom_new_date_value(&dv); \
417 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
420 return (Gedcom_ctxt)result; \
423 #define DEFINE_AGE_CB(STRUCTTYPE,CB_NAME,FIELD) \
424 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
426 Gom_ctxt result = NULL; \
430 struct STRUCTTYPE *obj \
431 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
433 struct age_value age = GEDCOM_AGE(parsed_value); \
434 obj->FIELD = gedcom_new_age_value(&age); \
438 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
441 return (Gedcom_ctxt)result; \
444 #define DEFINE_XREF_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE) \
445 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
447 Gom_ctxt result = NULL; \
451 struct STRUCTTYPE *obj \
452 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
453 struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value); \
455 xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string); \
458 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
461 return (Gedcom_ctxt)result; \
464 #define DEFINE_XREF_LIST_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE) \
465 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
467 Gom_ctxt result = NULL; \
471 struct STRUCTTYPE *obj \
472 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
473 struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value); \
474 struct xref_list *xrl; \
476 xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string); \
478 MAKE_CHAIN_ELT(xref_list, obj->FIELD, xrl); \
481 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
485 return (Gedcom_ctxt)result; \
488 #define DEFINE_NULL_CB(STRUCTTYPE,CB_NAME) \
489 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
491 Gom_ctxt result = NULL; \
495 struct STRUCTTYPE *obj \
496 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
498 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
500 return (Gedcom_ctxt)result; \
505 #endif /* __FUNC_TEMPLATE_H */