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 DESTROYFUNC(STRUCTTYPE) destroy_ ## STRUCTTYPE ## _record
29 #define GETXREFFUNC(STRUCTTYPE) gom_get_ ## STRUCTTYPE ## _by_xref
30 #define CLEANFUNC(STRUCTTYPE) STRUCTTYPE ## _cleanup
31 #define ADDFUNC(STRUCTTYPE) gom_add_ ## STRUCTTYPE
32 #define DELETEFUNC(STRUCTTYPE) gom_delete_ ## STRUCTTYPE
33 #define ADDFUNC2(T1,T2) T1 ## _add_ ## T2
34 #define ADDFUNC2_TOVAR(T1,T2,F) T1 ## _add_ ## T2 ## _to_ ## F
35 #define ADDFUNC2_NOLIST(T1,T2) ADDFUNC2(T1,T2)
36 #define ADDFUNC2_STR(T1,F) ADDFUNC2(T1,F)
37 #define ADDFUNC2_STRN(T1,F) ADDFUNC2(T1,F)
39 #define DECLARE_MAKEFUNC(STRUCTTYPE) \
40 struct STRUCTTYPE* MAKEFUNC(STRUCTTYPE)(const char* xref)
42 #define DECLARE_CLEANFUNC(STRUCTTYPE) \
43 void CLEANFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj)
45 #define DECLARE_ADDFUNC2(STRUCTTYPE,T2) \
46 void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
48 #define DECLARE_ADDFUNC2_TOVAR(STRUCTTYPE,T2,F) \
49 void ADDFUNC2_TOVAR(STRUCTTYPE,T2,F)(Gom_ctxt ctxt, struct T2* obj)
51 #define DECLARE_ADDFUNC2_NOLIST(STRUCTTYPE,T2) \
52 void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
54 #define DECLARE_ADDFUNC2_STR(STRUCTTYPE,F) \
55 void ADDFUNC2_STR(STRUCTTYPE,F)(Gom_ctxt ctxt, const char* str)
57 #define DECLARE_ADDFUNC2_STRN(STRUCTTYPE,F) \
58 void ADDFUNC2_STRN(STRUCTTYPE,F)(Gom_ctxt ctxt, const char* str)
60 /* Doubly-linked list, but last rec->next is NULL (doesn't go to first rec) */
61 #define LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
63 struct STRUCTTYPE *_local_obj = VAL; \
66 VAL->previous = _local_obj; \
71 FIRSTVAL->previous->next = VAL; \
72 VAL->previous = FIRSTVAL->previous; \
73 FIRSTVAL->previous = VAL; \
77 #define UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
79 struct STRUCTTYPE *_local_obj = VAL; \
80 if (VAL == FIRSTVAL) \
81 FIRSTVAL = _local_obj->next; \
83 VAL->previous->next = VAL->next; \
85 VAL->next->previous = VAL->previous; \
88 #define MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
90 VAL = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE)); \
94 memset (VAL, 0, sizeof(struct STRUCTTYPE)); \
95 LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL) \
99 #define DESTROY_CHAIN_ELTS(STRUCTTYPE, FIRSTVAL) \
102 struct STRUCTTYPE *runner, *next; \
105 next = runner->next; \
106 CLEANFUNC(STRUCTTYPE)(runner); \
113 /* General functions */
114 #define DEFINE_MAKEFUNC(STRUCTTYPE,FIRSTVAL) \
115 struct STRUCTTYPE* MAKEFUNC(STRUCTTYPE)(const char* xrefstr) { \
116 struct STRUCTTYPE* obj = NULL; \
118 MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj); \
120 obj->xrefstr = strdup(xrefstr); \
121 if (!obj->xrefstr) MEMORY_ERROR; \
127 #define DEFINE_DESTROYFUNC(STRUCTTYPE,FIRSTVAL) \
128 void CLEANFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj); \
129 void DESTROYFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) { \
131 CLEANFUNC(STRUCTTYPE)(obj); \
132 UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj); \
137 #define DEFINE_GETXREFFUNC(STRUCTTYPE,XREF_TYPE) \
138 struct STRUCTTYPE *GETXREFFUNC(STRUCTTYPE)(const char *xrefstr) \
140 struct xref_value* xr = gedcom_get_by_xref(xrefstr); \
141 if (xr && (xr->type == XREF_TYPE) && xr->object) \
142 return (struct STRUCTTYPE*)(xr->object); \
147 #define DEFINE_ADDFUNC(STRUCTTYPE,XREF_TYPE) \
148 struct STRUCTTYPE *ADDFUNC(STRUCTTYPE)(const char* xrefstr) \
150 struct STRUCTTYPE *obj = NULL; \
151 struct xref_value* xrv = gedcom_get_by_xref(xrefstr); \
153 gom_xref_already_in_use(xrefstr); \
155 obj = MAKEFUNC(STRUCTTYPE)(xrefstr); \
157 xrv = gedcom_add_xref(XREF_TYPE, xrefstr, (Gedcom_ctxt)obj); \
159 DESTROYFUNC(STRUCTTYPE)(obj); \
167 #define DEFINE_DELETEFUNC(STRUCTTYPE) \
168 int DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) \
172 result = gedcom_delete_xref(obj->xrefstr); \
174 DESTROYFUNC(STRUCTTYPE)(obj); \
179 #define DEFINE_ADDFUNC2(STRUCTTYPE,T2,FIELD) \
180 void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj) \
182 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
184 LINK_CHAIN_ELT(T2, obj->FIELD, addobj); \
187 #define DEFINE_ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD) \
188 void ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD)(Gom_ctxt ctxt, struct T2* addobj) \
190 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
192 LINK_CHAIN_ELT(T2, obj->FIELD, addobj); \
195 #define DEFINE_ADDFUNC2_NOLIST(STRUCTTYPE,T2, FIELD) \
196 void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj) \
198 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
200 obj->FIELD = addobj; \
203 #define DEFINE_ADDFUNC2_STR(STRUCTTYPE,FIELD) \
204 void ADDFUNC2_STR(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str) \
206 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
208 obj->FIELD = strdup(str); \
209 if (! obj->FIELD) MEMORY_ERROR; \
213 #define DEFINE_ADDFUNC2_STRN(STRUCTTYPE,FIELD,N) \
214 void ADDFUNC2_STRN(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str) \
216 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
219 while (i < N-1 && obj->FIELD[i]) i++; \
220 if (! obj->FIELD[i]) { \
221 obj->FIELD[i] = strdup(str); \
222 if (! obj->FIELD[i]) MEMORY_ERROR; \
227 /* Definition of callbacks */
228 #define _REC_PARAMS_ Gedcom_rec rec UNUSED, int level UNUSED, \
229 Gedcom_val xref UNUSED, char *tag UNUSED, \
230 char *raw_value UNUSED, int parsed_tag UNUSED, \
231 Gedcom_val parsed_value UNUSED
233 #define _REC_END_PARAMS_ Gedcom_rec rec UNUSED, Gedcom_ctxt self UNUSED, \
234 Gedcom_val parsed_value UNUSED
236 #define _ELT_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED, \
237 int level UNUSED, char *tag UNUSED, \
238 char *raw_value UNUSED, int parsed_tag UNUSED, \
239 Gedcom_val parsed_value UNUSED
241 #define _ELT_END_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED, \
242 Gedcom_ctxt self UNUSED, \
243 Gedcom_val parsed_value UNUSED
245 #define DEFINE_REC_CB(STRUCTTYPE,CB_NAME) \
246 Gedcom_ctxt CB_NAME(_REC_PARAMS_) \
248 struct xref_value* xr = GEDCOM_XREF_PTR(xref); \
250 xr->object = (Gedcom_ctxt) MAKEFUNC(STRUCTTYPE)(xr->string); \
252 return (Gedcom_ctxt) MAKE_GOM_CTXT(rec, STRUCTTYPE, xr->object); \
257 #define DEFINE_STRING_CB(STRUCTTYPE,CB_NAME,FIELD) \
258 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
260 Gom_ctxt result = NULL; \
264 struct STRUCTTYPE *obj \
265 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
267 char *str = GEDCOM_STRING(parsed_value); \
268 obj->FIELD = strdup(str); \
272 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
275 return (Gedcom_ctxt)result; \
278 #define DEFINE_STRING_END_CB(STRUCTTYPE,CB_NAME,FIELD) \
279 void CB_NAME(_ELT_END_PARAMS_) \
281 Gom_ctxt ctxt = (Gom_ctxt)self; \
285 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
287 char *str = GEDCOM_STRING(parsed_value); \
288 char *newvalue = strdup(str); \
292 obj->FIELD = newvalue; \
294 destroy_gom_ctxt(ctxt); \
298 #define DEFINE_STRING_END_REC_CB(STRUCTTYPE,CB_NAME,FIELD) \
299 void CB_NAME(_REC_END_PARAMS_) \
301 Gom_ctxt ctxt = (Gom_ctxt)self; \
305 struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt); \
307 char *str = GEDCOM_STRING(parsed_value); \
308 char *newvalue = strdup(str); \
312 obj->FIELD = newvalue; \
314 destroy_gom_ctxt(ctxt); \
318 #define DEFINE_DATE_CB(STRUCTTYPE,CB_NAME,FIELD) \
319 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
321 Gom_ctxt result = NULL; \
325 struct STRUCTTYPE *obj \
326 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
328 struct date_value dv = GEDCOM_DATE(parsed_value); \
329 obj->FIELD = gedcom_new_date_value(&dv); \
333 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
336 return (Gedcom_ctxt)result; \
339 #define DEFINE_AGE_CB(STRUCTTYPE,CB_NAME,FIELD) \
340 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
342 Gom_ctxt result = NULL; \
346 struct STRUCTTYPE *obj \
347 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
349 struct age_value age = GEDCOM_AGE(parsed_value); \
350 obj->FIELD = gedcom_new_age_value(&age); \
354 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
357 return (Gedcom_ctxt)result; \
360 #define DEFINE_XREF_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE) \
361 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
363 Gom_ctxt result = NULL; \
367 struct STRUCTTYPE *obj \
368 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
369 struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value); \
371 xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string); \
374 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
377 return (Gedcom_ctxt)result; \
380 #define DEFINE_XREF_LIST_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE) \
381 Gedcom_ctxt CB_NAME(_ELT_PARAMS_) \
383 Gom_ctxt result = NULL; \
387 struct STRUCTTYPE *obj \
388 = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent); \
389 struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value); \
390 struct xref_list *xrl; \
392 xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string); \
394 MAKE_CHAIN_ELT(xref_list, obj->FIELD, xrl); \
397 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
401 return (Gedcom_ctxt)result; \
404 #define DEFINE_NULL_CB(STRUCTTYPE,CB_NAME) \
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 result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj); \
416 return (Gedcom_ctxt)result; \
421 #endif /* __FUNC_TEMPLATE_H */