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 MAKELINKFUNC(STRUCTTYPE) gom_make_ ## STRUCTTYPE ## _link
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_ADDFUNC2(STRUCTTYPE,T2) \
53 void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
55 #define DECLARE_ADDFUNC2_TOVAR(STRUCTTYPE,T2,F) \
56 void ADDFUNC2_TOVAR(STRUCTTYPE,T2,F)(Gom_ctxt ctxt, struct T2* obj)
58 #define DECLARE_ADDFUNC2_NOLIST(STRUCTTYPE,T2) \
59 void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
61 #define DECLARE_ADDFUNC2_STR(STRUCTTYPE,F) \
62 void ADDFUNC2_STR(STRUCTTYPE,F)(Gom_ctxt ctxt, const char* str)
64 #define DECLARE_ADDFUNC2_STRN(STRUCTTYPE,F) \
65 void ADDFUNC2_STRN(STRUCTTYPE,F)(Gom_ctxt ctxt, const char* str)
67 /* Doubly-linked list, but last rec->next is NULL (doesn't go to first rec) */
68 #define LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
70 struct STRUCTTYPE *_local_obj = VAL; \
73 VAL->previous = _local_obj; \
78 FIRSTVAL->previous->next = VAL; \
79 VAL->previous = FIRSTVAL->previous; \
80 FIRSTVAL->previous = VAL; \
84 #define UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
86 struct STRUCTTYPE *_local_obj = VAL; \
87 if (VAL == FIRSTVAL) \
88 FIRSTVAL = _local_obj->next; \
90 VAL->previous->next = VAL->next; \
92 VAL->next->previous = VAL->previous; \
95 #define MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
97 VAL = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE)); \
101 memset (VAL, 0, sizeof(struct STRUCTTYPE)); \
102 LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
106 #define DESTROY_CHAIN_ELTS(STRUCTTYPE, FIRSTVAL) \
109 struct STRUCTTYPE *runner, *next; \
112 next = runner->next; \
113 CLEANFUNC(STRUCTTYPE)(runner); \
120 /* General functions */
121 #define DEFINE_MAKEFUNC(STRUCTTYPE,FIRSTVAL) \
122 struct STRUCTTYPE* MAKEFUNC(STRUCTTYPE)(const char* xrefstr) { \
123 struct STRUCTTYPE* obj = NULL; \
125 MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj); \
127 obj->xrefstr = strdup(xrefstr); \
128 if (!obj->xrefstr) MEMORY_ERROR; \
134 #define DEFINE_SUB_MAKEFUNC(STRUCTTYPE) \
135 struct STRUCTTYPE* SUB_MAKEFUNC(STRUCTTYPE)() { \
136 struct STRUCTTYPE* obj = NULL; \
137 obj = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE)); \
141 memset(obj, 0, sizeof(struct STRUCTTYPE)); \
145 #define DEFINE_DESTROYFUNC(STRUCTTYPE,FIRSTVAL) \
146 void CLEANFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj); \
147 void DESTROYFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) { \
149 CLEANFUNC(STRUCTTYPE)(obj); \
150 UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj); \
155 #define DEFINE_GETXREFFUNC(STRUCTTYPE,XREF_TYPE) \
156 struct STRUCTTYPE *GETXREFFUNC(STRUCTTYPE)(const char *xrefstr) \
158 struct xref_value* xr = gedcom_get_by_xref(xrefstr); \
159 if (xr && (xr->type == XREF_TYPE) && xr->object) \
160 return (struct STRUCTTYPE*)(xr->object); \
165 #define DEFINE_ADDFUNC(STRUCTTYPE,XREF_TYPE) \
166 struct STRUCTTYPE *ADDFUNC(STRUCTTYPE)(const char* xrefstr) \
168 struct STRUCTTYPE *obj = NULL; \
169 struct xref_value* xrv = gedcom_get_by_xref(xrefstr); \
171 gom_xref_already_in_use(xrefstr); \
173 obj = MAKEFUNC(STRUCTTYPE)(xrefstr); \
175 xrv = gedcom_add_xref(XREF_TYPE, xrefstr, (Gedcom_ctxt)obj); \
177 DESTROYFUNC(STRUCTTYPE)(obj); \
185 #define DEFINE_SUB_ADDFUNC(STRUCTTYPE) \
186 struct STRUCTTYPE *SUB_ADDFUNC(STRUCTTYPE)(struct STRUCTTYPE** addto) \
188 struct STRUCTTYPE *obj = NULL; \
189 if (addto && ! *addto) { \
190 obj = SUB_MAKEFUNC(STRUCTTYPE)(); \
191 if (obj) *addto = obj; \
196 #define DEFINE_DELETEFUNC(STRUCTTYPE) \
197 int DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) \
201 result = gedcom_delete_xref(obj->xrefstr); \
203 DESTROYFUNC(STRUCTTYPE)(obj); \
208 #define DEFINE_SUB_DELETEFUNC(STRUCTTYPE) \
209 int SUB_DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE** obj) \
213 CLEANFUNC(STRUCTTYPE)(*obj); \
221 #define DEFINE_MAKELINKFUNC(STRUCTTYPE,XREF_TYPE) \
222 struct xref_value* MAKELINKFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) \
224 struct xref_value* xr = NULL; \
225 if (obj && obj->xrefstr) { \
226 xr = gedcom_get_by_xref(obj->xrefstr); \
231 #define DEFINE_ADDFUNC2(STRUCTTYPE,T2,FIELD) \
232 void ADDFUNC2(STRUCTTYPE,T2)(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_TOVAR(STRUCTTYPE,T2,FIELD) \
240 void ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD)(Gom_ctxt ctxt, struct T2* addobj) \
242 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
244 LINK_CHAIN_ELT(T2, obj->FIELD, addobj); \
247 #define DEFINE_ADDFUNC2_NOLIST(STRUCTTYPE,T2, FIELD) \
248 void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj) \
250 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
252 obj->FIELD = addobj; \
255 #define DEFINE_ADDFUNC2_STR(STRUCTTYPE,FIELD) \
256 void ADDFUNC2_STR(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str) \
258 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
260 obj->FIELD = strdup(str); \
261 if (! obj->FIELD) MEMORY_ERROR; \
265 #define DEFINE_ADDFUNC2_STRN(STRUCTTYPE,FIELD,N) \
266 void ADDFUNC2_STRN(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str) \
268 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
271 while (i < N-1 && obj->FIELD[i]) i++; \
272 if (! obj->FIELD[i]) { \
273 obj->FIELD[i] = strdup(str); \
274 if (! obj->FIELD[i]) MEMORY_ERROR; \
279 /* Definition of callbacks */
280 #define _REC_PARAMS_ Gedcom_rec rec UNUSED, int level UNUSED, \
281 Gedcom_val xref UNUSED, char *tag UNUSED, \
282 char *raw_value UNUSED, int parsed_tag UNUSED, \
283 Gedcom_val parsed_value UNUSED
285 #define _REC_END_PARAMS_ Gedcom_rec rec UNUSED, Gedcom_ctxt self UNUSED, \
286 Gedcom_val parsed_value UNUSED
288 #define _ELT_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED, \
289 int level UNUSED, char *tag UNUSED, \
290 char *raw_value UNUSED, int parsed_tag UNUSED, \
291 Gedcom_val parsed_value UNUSED
293 #define _ELT_END_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED, \
294 Gedcom_ctxt self UNUSED, \
295 Gedcom_val parsed_value UNUSED
297 #define DEFINE_REC_CB(STRUCTTYPE,CB_NAME) \
298 Gedcom_ctxt CB_NAME(_REC_PARAMS_) \
300 struct xref_value* xr = GEDCOM_XREF_PTR(xref); \
302 xr->object = (Gedcom_ctxt) MAKEFUNC(STRUCTTYPE)(xr->string); \
304 return (Gedcom_ctxt) MAKE_GOM_CTXT(rec, STRUCTTYPE, xr->object); \
309 #define DEFINE_STRING_CB(STRUCTTYPE,CB_NAME,FIELD) \
310 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
312 Gom_ctxt result = NULL; \
316 struct STRUCTTYPE *obj \
317 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
319 char *str = GEDCOM_STRING(parsed_value); \
320 obj->FIELD = strdup(str); \
324 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
327 return (Gedcom_ctxt)result; \
330 #define DEFINE_STRING_END_CB(STRUCTTYPE,CB_NAME,FIELD) \
331 void CB_NAME(_ELT_END_PARAMS_) \
333 Gom_ctxt ctxt = (Gom_ctxt)self; \
337 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
339 char *str = GEDCOM_STRING(parsed_value); \
340 char *newvalue = strdup(str); \
344 obj->FIELD = newvalue; \
346 destroy_gom_ctxt(ctxt); \
350 #define DEFINE_STRING_END_REC_CB(STRUCTTYPE,CB_NAME,FIELD) \
351 void CB_NAME(_REC_END_PARAMS_) \
353 Gom_ctxt ctxt = (Gom_ctxt)self; \
357 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
359 char *str = GEDCOM_STRING(parsed_value); \
360 char *newvalue = strdup(str); \
364 obj->FIELD = newvalue; \
366 destroy_gom_ctxt(ctxt); \
370 #define DEFINE_DATE_CB(STRUCTTYPE,CB_NAME,FIELD) \
371 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
373 Gom_ctxt result = NULL; \
377 struct STRUCTTYPE *obj \
378 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
380 struct date_value dv = GEDCOM_DATE(parsed_value); \
381 obj->FIELD = gedcom_new_date_value(&dv); \
385 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
388 return (Gedcom_ctxt)result; \
391 #define DEFINE_AGE_CB(STRUCTTYPE,CB_NAME,FIELD) \
392 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
394 Gom_ctxt result = NULL; \
398 struct STRUCTTYPE *obj \
399 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
401 struct age_value age = GEDCOM_AGE(parsed_value); \
402 obj->FIELD = gedcom_new_age_value(&age); \
406 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
409 return (Gedcom_ctxt)result; \
412 #define DEFINE_XREF_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE) \
413 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
415 Gom_ctxt result = NULL; \
419 struct STRUCTTYPE *obj \
420 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
421 struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value); \
423 xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string); \
426 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
429 return (Gedcom_ctxt)result; \
432 #define DEFINE_XREF_LIST_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE) \
433 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
435 Gom_ctxt result = NULL; \
439 struct STRUCTTYPE *obj \
440 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
441 struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value); \
442 struct xref_list *xrl; \
444 xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string); \
446 MAKE_CHAIN_ELT(xref_list, obj->FIELD, xrl); \
449 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
453 return (Gedcom_ctxt)result; \
456 #define DEFINE_NULL_CB(STRUCTTYPE,CB_NAME) \
457 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
459 Gom_ctxt result = NULL; \
463 struct STRUCTTYPE *obj \
464 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
466 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
468 return (Gedcom_ctxt)result; \
473 #endif /* __FUNC_TEMPLATE_H */