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 SUB_ADDFUNC(STRUCTTYPE) gom_add_new_ ## STRUCTTYPE
35 #define UNREFALLFUNC(STRUCTTYPE) STRUCTTYPE ## _unref_all
36 #define DELETEFUNC(STRUCTTYPE) gom_delete_ ## STRUCTTYPE
37 #define SUB_DELETEFUNC(STRUCTTYPE) gom_delete_ ## STRUCTTYPE
38 #define SUB_FINDFUNC(STRUCTTYPE) find_ ## STRUCTTYPE
39 #define SUB_REMOVEFUNC(STRUCTTYPE) gom_remove_ ## STRUCTTYPE
40 #define SUB_MOVEFUNC(STRUCTTYPE) gom_move_ ## STRUCTTYPE
41 #define ADDFUNC2(T1,T2) T1 ## _add_ ## T2
42 #define ADDFUNC2_TOVAR(T1,T2,F) T1 ## _add_ ## T2 ## _to_ ## F
43 #define ADDFUNC2_NOLIST(T1,T2) ADDFUNC2(T1,T2)
44 #define ADDFUNC2_STR(T1,F) ADDFUNC2(T1,F)
45 #define ADDFUNC2_STRN(T1,F) ADDFUNC2(T1,F)
47 #define DECLARE_MAKEFUNC(STRUCTTYPE) \
48 struct STRUCTTYPE* MAKEFUNC(STRUCTTYPE)(const char* xref)
50 #define DECLARE_SUB_MAKEFUNC(STRUCTTYPE) \
51 struct STRUCTTYPE* SUB_MAKEFUNC(STRUCTTYPE)()
53 #define DECLARE_CLEANFUNC(STRUCTTYPE) \
54 void CLEANFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj)
56 #define DECLARE_UNREFALLFUNC(STRUCTTYPE) \
57 void UNREFALLFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj)
59 #define DECLARE_ADDFUNC2(STRUCTTYPE,T2) \
60 void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
62 #define DECLARE_ADDFUNC2_TOVAR(STRUCTTYPE,T2,F) \
63 void ADDFUNC2_TOVAR(STRUCTTYPE,T2,F)(Gom_ctxt ctxt, struct T2* obj)
65 #define DECLARE_ADDFUNC2_NOLIST(STRUCTTYPE,T2) \
66 void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
68 #define DECLARE_ADDFUNC2_STR(STRUCTTYPE,F) \
69 void ADDFUNC2_STR(STRUCTTYPE,F)(Gom_ctxt ctxt, const char* str)
71 #define DECLARE_ADDFUNC2_STRN(STRUCTTYPE,F) \
72 void ADDFUNC2_STRN(STRUCTTYPE,F)(Gom_ctxt ctxt, const char* str)
74 /* Doubly-linked list, but last rec->next is NULL (doesn't go to first rec) */
75 #define LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
77 struct STRUCTTYPE *_local_obj = VAL; \
80 VAL->previous = _local_obj; \
85 (FIRSTVAL)->previous->next = VAL; \
86 VAL->previous = (FIRSTVAL)->previous; \
87 (FIRSTVAL)->previous = VAL; \
91 #define UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
93 struct STRUCTTYPE *_local_obj = VAL; \
94 if (VAL == FIRSTVAL) \
95 FIRSTVAL = _local_obj->next; \
97 VAL->previous->next = VAL->next; \
99 VAL->next->previous = VAL->previous; \
101 (FIRSTVAL)->previous = VAL->previous; \
104 #define MOVE_CHAIN_ELT(STRUCTTYPE, DIR, FIRSTVAL, VAL) \
106 struct STRUCTTYPE *first, *second; \
107 if (DIR == MOVE_UP) { \
108 first = VAL->previous; \
113 second = VAL->next; \
115 if (second && (second != FIRSTVAL)) { \
116 if (first != FIRSTVAL) \
117 first->previous->next = second; \
122 second->next->previous = first; \
124 (FIRSTVAL)->previous = first; \
126 first->next = second->next; \
127 second->next = first; \
129 second->previous = first->previous; \
130 first->previous = second; \
133 gom_move_error(#STRUCTTYPE); \
137 #define MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
139 VAL = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE)); \
143 memset (VAL, 0, sizeof(struct STRUCTTYPE)); \
144 LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
148 #define DESTROY_CHAIN_ELTS(STRUCTTYPE, FIRSTVAL) \
151 struct STRUCTTYPE *runner, *next; \
155 next = runner->next; \
156 CLEANFUNC(STRUCTTYPE)(runner); \
163 /* General functions */
164 #define DEFINE_MAKEFUNC(STRUCTTYPE,FIRSTVAL) \
165 struct STRUCTTYPE* MAKEFUNC(STRUCTTYPE)(const char* xrefstr) { \
166 struct STRUCTTYPE* obj = NULL; \
168 MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj); \
170 obj->xrefstr = strdup(xrefstr); \
171 if (!obj->xrefstr) MEMORY_ERROR; \
177 #define DEFINE_SUB_MAKEFUNC(STRUCTTYPE) \
178 struct STRUCTTYPE* SUB_MAKEFUNC(STRUCTTYPE)() { \
179 struct STRUCTTYPE* obj = NULL; \
180 obj = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE)); \
184 memset(obj, 0, sizeof(struct STRUCTTYPE)); \
188 #define DEFINE_DESTROYFUNC(STRUCTTYPE,FIRSTVAL) \
189 DECLARE_CLEANFUNC(STRUCTTYPE); \
190 void DESTROYFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) { \
192 CLEANFUNC(STRUCTTYPE)(obj); \
193 UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj); \
198 #define DEFINE_GETXREFFUNC(STRUCTTYPE,XREF_TYPE) \
199 struct STRUCTTYPE *GETXREFFUNC(STRUCTTYPE)(const char *xrefstr) \
201 struct xref_value* xr = gedcom_get_by_xref(xrefstr); \
202 if (xr && (xr->type == XREF_TYPE) && xr->object) \
203 return (struct STRUCTTYPE*)(xr->object); \
208 #define DEFINE_ADDFUNC(STRUCTTYPE,XREF_TYPE) \
209 struct STRUCTTYPE *ADDFUNC(STRUCTTYPE)(const char* xrefstr) \
211 struct STRUCTTYPE *obj = NULL; \
212 struct xref_value* xrv = gedcom_get_by_xref(xrefstr); \
214 gom_xref_already_in_use(xrefstr); \
216 obj = MAKEFUNC(STRUCTTYPE)(xrefstr); \
218 xrv = gedcom_add_xref(XREF_TYPE, xrefstr, (Gedcom_ctxt)obj); \
220 DESTROYFUNC(STRUCTTYPE)(obj); \
228 #define DEFINE_SUB_SETFUNC(STRUCTTYPE) \
229 struct STRUCTTYPE *SUB_SETFUNC(STRUCTTYPE)(struct STRUCTTYPE** addto) \
231 struct STRUCTTYPE *obj = NULL; \
232 if (addto && ! *addto) { \
233 obj = SUB_MAKEFUNC(STRUCTTYPE)(); \
234 if (obj) *addto = obj; \
239 #define DEFINE_SUB_ADDFUNC(STRUCTTYPE) \
240 struct STRUCTTYPE *SUB_ADDFUNC(STRUCTTYPE)(struct STRUCTTYPE** addto) \
242 struct STRUCTTYPE *obj = NULL; \
244 MAKE_CHAIN_ELT(STRUCTTYPE, *addto, obj); \
249 #define DEFINE_DELETEFUNC(STRUCTTYPE) \
250 DECLARE_UNREFALLFUNC(STRUCTTYPE); \
251 int DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) \
255 result = gedcom_delete_xref(obj->xrefstr); \
257 UNREFALLFUNC(STRUCTTYPE)(obj); \
258 DESTROYFUNC(STRUCTTYPE)(obj); \
264 #define DEFINE_SUB_DELETEFUNC(STRUCTTYPE) \
265 int SUB_DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE** obj) \
269 UNREFALLFUNC(STRUCTTYPE)(*obj); \
270 CLEANFUNC(STRUCTTYPE)(*obj); \
277 #define DEFINE_SUB_FINDFUNC(STRUCTTYPE) \
278 struct STRUCTTYPE* SUB_FINDFUNC(STRUCTTYPE)(struct STRUCTTYPE** data, \
279 struct STRUCTTYPE* obj) \
281 struct STRUCTTYPE* result = NULL; \
282 struct STRUCTTYPE* runner; \
283 for (runner = *data ; runner ; runner = runner->next) { \
284 if (runner == obj) { \
290 gom_find_error(#STRUCTTYPE); \
294 #define DEFINE_SUB_REMOVEFUNC(STRUCTTYPE) \
295 int SUB_REMOVEFUNC(STRUCTTYPE) (struct STRUCTTYPE** data, \
296 struct STRUCTTYPE* obj) \
300 struct STRUCTTYPE* toremove = SUB_FINDFUNC(STRUCTTYPE)(data, obj); \
302 UNLINK_CHAIN_ELT(STRUCTTYPE, *data, toremove); \
303 CLEANFUNC(STRUCTTYPE)(toremove); \
304 SAFE_FREE(toremove); \
311 #define DEFINE_SUB_MOVEFUNC(STRUCTTYPE) \
312 int SUB_MOVEFUNC(STRUCTTYPE)(Gom_direction dir, struct STRUCTTYPE** data, \
313 struct STRUCTTYPE* obj) \
317 struct STRUCTTYPE* tomove = SUB_FINDFUNC(STRUCTTYPE)(data, obj); \
319 MOVE_CHAIN_ELT(STRUCTTYPE, dir, *data, tomove); \
326 #define DEFINE_ADDFUNC2(STRUCTTYPE,T2,FIELD) \
327 void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj) \
329 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
331 LINK_CHAIN_ELT(T2, obj->FIELD, addobj); \
334 #define DEFINE_ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD) \
335 void ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD)(Gom_ctxt ctxt, struct T2* addobj) \
337 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
339 LINK_CHAIN_ELT(T2, obj->FIELD, addobj); \
342 #define DEFINE_ADDFUNC2_NOLIST(STRUCTTYPE,T2, FIELD) \
343 void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj) \
345 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
347 obj->FIELD = addobj; \
350 #define DEFINE_ADDFUNC2_STR(STRUCTTYPE,FIELD) \
351 void ADDFUNC2_STR(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str) \
353 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
355 obj->FIELD = strdup(str); \
356 if (! obj->FIELD) MEMORY_ERROR; \
360 #define DEFINE_ADDFUNC2_STRN(STRUCTTYPE,FIELD,N) \
361 void ADDFUNC2_STRN(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str) \
363 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
366 while (i < N-1 && obj->FIELD[i]) i++; \
367 if (! obj->FIELD[i]) { \
368 obj->FIELD[i] = strdup(str); \
369 if (! obj->FIELD[i]) MEMORY_ERROR; \
374 /* Definition of callbacks */
375 #define _REC_PARAMS_ Gedcom_rec rec UNUSED, int level UNUSED, \
376 Gedcom_val xref UNUSED, char *tag UNUSED, \
377 char *raw_value UNUSED, int parsed_tag UNUSED, \
378 Gedcom_val parsed_value UNUSED
380 #define _REC_END_PARAMS_ Gedcom_rec rec UNUSED, Gedcom_ctxt self UNUSED, \
381 Gedcom_val parsed_value UNUSED
383 #define _ELT_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED, \
384 int level UNUSED, char *tag UNUSED, \
385 char *raw_value UNUSED, int parsed_tag UNUSED, \
386 Gedcom_val parsed_value UNUSED
388 #define _ELT_END_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED, \
389 Gedcom_ctxt self UNUSED, \
390 Gedcom_val parsed_value UNUSED
392 #define DEFINE_REC_CB(STRUCTTYPE,CB_NAME) \
393 Gedcom_ctxt CB_NAME(_REC_PARAMS_) \
395 struct xref_value* xr = GEDCOM_XREF_PTR(xref); \
397 xr->object = (Gedcom_ctxt) MAKEFUNC(STRUCTTYPE)(xr->string); \
399 return (Gedcom_ctxt) MAKE_GOM_CTXT(rec, STRUCTTYPE, xr->object); \
404 #define DEFINE_STRING_CB(STRUCTTYPE,CB_NAME,FIELD) \
405 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
407 Gom_ctxt result = NULL; \
411 struct STRUCTTYPE *obj \
412 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
414 char *str = GEDCOM_STRING(parsed_value); \
415 obj->FIELD = strdup(str); \
419 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
422 return (Gedcom_ctxt)result; \
425 #define DEFINE_STRING_END_CB(STRUCTTYPE,CB_NAME,FIELD) \
426 void CB_NAME(_ELT_END_PARAMS_) \
428 Gom_ctxt ctxt = (Gom_ctxt)self; \
432 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
434 char *str = GEDCOM_STRING(parsed_value); \
435 char *newvalue = strdup(str); \
439 obj->FIELD = newvalue; \
441 destroy_gom_ctxt(ctxt); \
445 #define DEFINE_STRING_END_REC_CB(STRUCTTYPE,CB_NAME,FIELD) \
446 void CB_NAME(_REC_END_PARAMS_) \
448 Gom_ctxt ctxt = (Gom_ctxt)self; \
452 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
454 char *str = GEDCOM_STRING(parsed_value); \
455 char *newvalue = strdup(str); \
459 obj->FIELD = newvalue; \
461 destroy_gom_ctxt(ctxt); \
465 #define DEFINE_DATE_CB(STRUCTTYPE,CB_NAME,FIELD) \
466 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
468 Gom_ctxt result = NULL; \
472 struct STRUCTTYPE *obj \
473 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
475 struct date_value dv = GEDCOM_DATE(parsed_value); \
476 obj->FIELD = gedcom_new_date_value(&dv); \
480 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
483 return (Gedcom_ctxt)result; \
486 #define DEFINE_AGE_CB(STRUCTTYPE,CB_NAME,FIELD) \
487 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
489 Gom_ctxt result = NULL; \
493 struct STRUCTTYPE *obj \
494 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
496 struct age_value age = GEDCOM_AGE(parsed_value); \
497 obj->FIELD = gedcom_new_age_value(&age); \
501 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
504 return (Gedcom_ctxt)result; \
507 #define DEFINE_XREF_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE) \
508 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
510 Gom_ctxt result = NULL; \
514 struct STRUCTTYPE *obj \
515 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
516 struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value); \
518 xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string); \
521 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
524 return (Gedcom_ctxt)result; \
527 #define DEFINE_XREF_LIST_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE) \
528 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
530 Gom_ctxt result = NULL; \
534 struct STRUCTTYPE *obj \
535 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
536 struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value); \
537 struct xref_list *xrl; \
539 xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string); \
541 MAKE_CHAIN_ELT(xref_list, obj->FIELD, xrl); \
544 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
548 return (Gedcom_ctxt)result; \
551 #define DEFINE_NULL_CB(STRUCTTYPE,CB_NAME) \
552 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
554 Gom_ctxt result = NULL; \
558 struct STRUCTTYPE *obj \
559 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
561 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
563 return (Gedcom_ctxt)result; \
568 #endif /* __FUNC_TEMPLATE_H */