a21424d1b425b1847d3f2123b556da5a0758671d
[gedcom-parse.git] / gom / func_template.h
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.
5
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.
10
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.
15
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
19    02111-1307 USA.  */
20
21 /* $Id$ */
22 /* $Name$ */
23
24 #ifndef __FUNC_TEMPLATE_H
25 #define __FUNC_TEMPLATE_H
26
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 ADDFUNC2(T1,T2)          T1 ## _add_ ## T2
37 #define ADDFUNC2_TOVAR(T1,T2,F)  T1 ## _add_ ## T2 ## _to_ ## F
38 #define ADDFUNC2_NOLIST(T1,T2)   ADDFUNC2(T1,T2)
39 #define ADDFUNC2_STR(T1,F)       ADDFUNC2(T1,F)
40 #define ADDFUNC2_STRN(T1,F)      ADDFUNC2(T1,F)
41
42 #define DECLARE_MAKEFUNC(STRUCTTYPE)                                          \
43   struct STRUCTTYPE* MAKEFUNC(STRUCTTYPE)(const char* xref)
44
45 #define DECLARE_SUB_MAKEFUNC(STRUCTTYPE)                                      \
46   struct STRUCTTYPE* SUB_MAKEFUNC(STRUCTTYPE)()
47
48 #define DECLARE_CLEANFUNC(STRUCTTYPE)                                         \
49   void CLEANFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj)
50
51 #define DECLARE_ADDFUNC2(STRUCTTYPE,T2)                                       \
52   void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
53
54 #define DECLARE_ADDFUNC2_TOVAR(STRUCTTYPE,T2,F)                               \
55   void ADDFUNC2_TOVAR(STRUCTTYPE,T2,F)(Gom_ctxt ctxt, struct T2* obj)
56
57 #define DECLARE_ADDFUNC2_NOLIST(STRUCTTYPE,T2)                                \
58   void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
59
60 #define DECLARE_ADDFUNC2_STR(STRUCTTYPE,F)                                    \
61   void ADDFUNC2_STR(STRUCTTYPE,F)(Gom_ctxt ctxt, const char* str)
62
63 #define DECLARE_ADDFUNC2_STRN(STRUCTTYPE,F)                                   \
64   void ADDFUNC2_STRN(STRUCTTYPE,F)(Gom_ctxt ctxt, const char* str)
65
66 /* Doubly-linked list, but last rec->next is NULL (doesn't go to first rec) */
67 #define LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                             \
68   {                                                                           \
69     struct STRUCTTYPE *_local_obj = VAL;                                      \
70     if (! FIRSTVAL) {                                                         \
71       VAL->next = NULL;                                                       \
72       VAL->previous = _local_obj;                                             \
73       FIRSTVAL = VAL;                                                         \
74     }                                                                         \
75     else {                                                                    \
76       VAL->next = NULL;                                                       \
77       (FIRSTVAL)->previous->next = VAL;                                       \
78       VAL->previous = (FIRSTVAL)->previous;                                   \
79       (FIRSTVAL)->previous = VAL;                                             \
80     }                                                                         \
81   }
82
83 #define UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                           \
84   {                                                                           \
85     struct STRUCTTYPE *_local_obj = VAL;                                      \
86     if (VAL == FIRSTVAL)                                                      \
87       FIRSTVAL = _local_obj->next;                                            \
88     else                                                                      \
89       VAL->previous->next = VAL->next;                                        \
90     if (VAL->next)                                                            \
91       VAL->next->previous = VAL->previous;                                    \
92     else if (FIRSTVAL)                                                        \
93       (FIRSTVAL)->previous = VAL->previous;                                   \
94   }
95
96 #define MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                             \
97   {                                                                           \
98     VAL = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE));             \
99     if (! VAL)                                                                \
100       MEMORY_ERROR;                                                           \
101     else {                                                                    \
102       memset (VAL, 0, sizeof(struct STRUCTTYPE));                             \
103       LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                               \
104     }                                                                         \
105   }
106
107 #define DESTROY_CHAIN_ELTS(STRUCTTYPE, FIRSTVAL)                              \
108   {                                                                           \
109     if (FIRSTVAL) {                                                           \
110       struct STRUCTTYPE *runner, *next;                                       \
111       runner = FIRSTVAL;                                                      \
112       FIRSTVAL = NULL;                                                        \
113       while (runner) {                                                        \
114         next = runner->next;                                                  \
115         CLEANFUNC(STRUCTTYPE)(runner);                                        \
116         SAFE_FREE(runner);                                                    \
117         runner = next;                                                        \
118       }                                                                       \
119     }                                                                         \
120   }
121
122 /* General functions */
123 #define DEFINE_MAKEFUNC(STRUCTTYPE,FIRSTVAL)                                  \
124   struct STRUCTTYPE* MAKEFUNC(STRUCTTYPE)(const char* xrefstr) {              \
125     struct STRUCTTYPE* obj = NULL;                                            \
126     if (xrefstr) {                                                            \
127       MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj);                              \
128       if (obj) {                                                              \
129         obj->xrefstr = strdup(xrefstr);                                       \
130         if (!obj->xrefstr) MEMORY_ERROR;                                      \
131       }                                                                       \
132     }                                                                         \
133     return obj;                                                               \
134   }
135
136 #define DEFINE_SUB_MAKEFUNC(STRUCTTYPE)                                       \
137   struct STRUCTTYPE* SUB_MAKEFUNC(STRUCTTYPE)() {                             \
138     struct STRUCTTYPE* obj = NULL;                                            \
139     obj = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE));             \
140     if (!obj)                                                                 \
141       MEMORY_ERROR;                                                           \
142     else                                                                      \
143       memset(obj, 0, sizeof(struct STRUCTTYPE));                              \
144     return obj;                                                               \
145   }
146
147 #define DEFINE_DESTROYFUNC(STRUCTTYPE,FIRSTVAL)                               \
148   void CLEANFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj);                         \
149   void DESTROYFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) {                      \
150     if (obj) {                                                                \
151       CLEANFUNC(STRUCTTYPE)(obj);                                             \
152       UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj);                            \
153       SAFE_FREE(obj);                                                         \
154     }                                                                         \
155   }
156
157 #define DEFINE_GETXREFFUNC(STRUCTTYPE,XREF_TYPE)                              \
158   struct STRUCTTYPE *GETXREFFUNC(STRUCTTYPE)(const char *xrefstr)             \
159   {                                                                           \
160     struct xref_value* xr = gedcom_get_by_xref(xrefstr);                      \
161     if (xr && (xr->type == XREF_TYPE) && xr->object)                          \
162       return (struct STRUCTTYPE*)(xr->object);                                \
163     else                                                                      \
164       return NULL;                                                            \
165   }
166
167 #define DEFINE_ADDFUNC(STRUCTTYPE,XREF_TYPE)                                  \
168   struct STRUCTTYPE *ADDFUNC(STRUCTTYPE)(const char* xrefstr)                 \
169   {                                                                           \
170     struct STRUCTTYPE *obj = NULL;                                            \
171     struct xref_value* xrv = gedcom_get_by_xref(xrefstr);                     \
172     if (xrv)                                                                  \
173       gom_xref_already_in_use(xrefstr);                                       \
174     else {                                                                    \
175       obj = MAKEFUNC(STRUCTTYPE)(xrefstr);                                    \
176       if (obj) {                                                              \
177         xrv = gedcom_add_xref(XREF_TYPE, xrefstr, (Gedcom_ctxt)obj);          \
178         if (!xrv) {                                                           \
179           DESTROYFUNC(STRUCTTYPE)(obj);                                       \
180           obj = NULL;                                                         \
181         }                                                                     \
182       }                                                                       \
183     }                                                                         \
184     return obj;                                                               \
185   }
186
187 #define DEFINE_SUB_ADDFUNC(STRUCTTYPE)                                        \
188   struct STRUCTTYPE *SUB_ADDFUNC(STRUCTTYPE)(struct STRUCTTYPE** addto)       \
189   {                                                                           \
190     struct STRUCTTYPE *obj = NULL;                                            \
191     if (addto && ! *addto) {                                                  \
192       obj = SUB_MAKEFUNC(STRUCTTYPE)();                                       \
193       if (obj) *addto = obj;                                                  \
194     }                                                                         \
195     return obj;                                                               \
196   }
197
198 /* TODO: Check whether there are still xrefs linked in */
199 #define DEFINE_DELETEFUNC(STRUCTTYPE)                                         \
200   int DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj)                          \
201   {                                                                           \
202     int result = 1;                                                           \
203     if (obj) {                                                                \
204       result = gedcom_delete_xref(obj->xrefstr);                              \
205       if (result == 0)                                                        \
206         DESTROYFUNC(STRUCTTYPE)(obj);                                         \
207     }                                                                         \
208     return result;                                                            \
209   }
210
211 #define DEFINE_SUB_DELETEFUNC(STRUCTTYPE)                                     \
212   int SUB_DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE** obj)                     \
213   {                                                                           \
214     int result = 1;                                                           \
215     if (obj && *obj) {                                                        \
216       CLEANFUNC(STRUCTTYPE)(*obj);                                            \
217       SAFE_FREE(*obj);                                                        \
218       result = 0;                                                             \
219     }                                                                         \
220     return result;                                                            \
221   }
222
223 #define DEFINE_ADDFUNC2(STRUCTTYPE,T2,FIELD)                                  \
224   void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj)              \
225   {                                                                           \
226     struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt);                \
227     if (obj)                                                                  \
228       LINK_CHAIN_ELT(T2, obj->FIELD, addobj);                                 \
229   }
230
231 #define DEFINE_ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD)                            \
232   void ADDFUNC2_TOVAR(STRUCTTYPE,T2,FIELD)(Gom_ctxt ctxt, struct T2* addobj)  \
233   {                                                                           \
234     struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt);                \
235     if (obj)                                                                  \
236       LINK_CHAIN_ELT(T2, obj->FIELD, addobj);                                 \
237   }
238
239 #define DEFINE_ADDFUNC2_NOLIST(STRUCTTYPE,T2, FIELD)                          \
240   void ADDFUNC2_NOLIST(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* addobj)       \
241   {                                                                           \
242     struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt);                \
243     if (obj)                                                                  \
244       obj->FIELD = addobj;                                                    \
245   }
246
247 #define DEFINE_ADDFUNC2_STR(STRUCTTYPE,FIELD)                                 \
248 void ADDFUNC2_STR(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str)           \
249 {                                                                             \
250   struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt);                  \
251   if (obj) {                                                                  \
252     obj->FIELD = strdup(str);                                                 \
253     if (! obj->FIELD) MEMORY_ERROR;                                           \
254   }                                                                           \
255 }
256
257 #define DEFINE_ADDFUNC2_STRN(STRUCTTYPE,FIELD,N)                              \
258 void ADDFUNC2_STRN(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str)          \
259 {                                                                             \
260   struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt);                  \
261   if (obj) {                                                                  \
262     int i = 0;                                                                \
263     while (i < N-1 && obj->FIELD[i]) i++;                                     \
264     if (! obj->FIELD[i]) {                                                    \
265       obj->FIELD[i] = strdup(str);                                            \
266       if (! obj->FIELD[i]) MEMORY_ERROR;                                      \
267     }                                                                         \
268   }                                                                           \
269 }
270
271 /* Definition of callbacks */
272 #define _REC_PARAMS_ Gedcom_rec rec UNUSED, int level UNUSED,                 \
273                      Gedcom_val xref UNUSED, char *tag UNUSED,                \
274                      char *raw_value UNUSED, int parsed_tag UNUSED,           \
275                      Gedcom_val parsed_value UNUSED
276
277 #define _REC_END_PARAMS_ Gedcom_rec rec UNUSED, Gedcom_ctxt self UNUSED,      \
278                          Gedcom_val parsed_value UNUSED
279
280 #define _ELT_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED,        \
281                      int level UNUSED, char *tag UNUSED,                      \
282                      char *raw_value UNUSED, int parsed_tag UNUSED,           \
283                      Gedcom_val parsed_value UNUSED
284
285 #define _ELT_END_PARAMS_ Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED,    \
286                          Gedcom_ctxt self UNUSED,                             \
287                          Gedcom_val parsed_value UNUSED
288
289 #define DEFINE_REC_CB(STRUCTTYPE,CB_NAME)                                     \
290   Gedcom_ctxt CB_NAME(_REC_PARAMS_)                                           \
291   {                                                                           \
292     struct xref_value* xr = GEDCOM_XREF_PTR(xref);                            \
293     if (! xr->object)                                                         \
294       xr->object = (Gedcom_ctxt) MAKEFUNC(STRUCTTYPE)(xr->string);            \
295     if (xr->object)                                                           \
296       return (Gedcom_ctxt) MAKE_GOM_CTXT(rec, STRUCTTYPE, xr->object);        \
297     else                                                                      \
298       return NULL;                                                            \
299   }
300
301 #define DEFINE_STRING_CB(STRUCTTYPE,CB_NAME,FIELD)                            \
302   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
303   {                                                                           \
304     Gom_ctxt result = NULL;                                                   \
305     if (! parent)                                                             \
306       NO_CONTEXT;                                                             \
307     else {                                                                    \
308       struct STRUCTTYPE *obj                                                  \
309         = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
310       if (obj) {                                                              \
311         char *str = GEDCOM_STRING(parsed_value);                              \
312         obj->FIELD = strdup(str);                                             \
313         if (! obj->FIELD)                                                     \
314           MEMORY_ERROR;                                                       \
315         else                                                                  \
316           result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                       \
317       }                                                                       \
318     }                                                                         \
319     return (Gedcom_ctxt)result;                                               \
320   }
321
322 #define DEFINE_STRING_END_CB(STRUCTTYPE,CB_NAME,FIELD)                        \
323   void CB_NAME(_ELT_END_PARAMS_)                                              \
324   {                                                                           \
325     Gom_ctxt ctxt = (Gom_ctxt)self;                                           \
326     if (! ctxt)                                                               \
327       NO_CONTEXT;                                                             \
328     else {                                                                    \
329       struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt);              \
330       if (obj) {                                                              \
331         char *str = GEDCOM_STRING(parsed_value);                              \
332         char *newvalue = strdup(str);                                         \
333         if (! newvalue)                                                       \
334           MEMORY_ERROR;                                                       \
335         else                                                                  \
336           obj->FIELD = newvalue;                                              \
337       }                                                                       \
338       destroy_gom_ctxt(ctxt);                                                 \
339     }                                                                         \
340   }
341
342 #define DEFINE_STRING_END_REC_CB(STRUCTTYPE,CB_NAME,FIELD)                    \
343   void CB_NAME(_REC_END_PARAMS_)                                              \
344   {                                                                           \
345     Gom_ctxt ctxt = (Gom_ctxt)self;                                           \
346     if (! ctxt)                                                               \
347       NO_CONTEXT;                                                             \
348     else {                                                                    \
349       struct STRUCTTYPE *obj = SAFE_CTXT_CAST(STRUCTTYPE, ctxt);              \
350       if (obj) {                                                              \
351         char *str = GEDCOM_STRING(parsed_value);                              \
352         char *newvalue = strdup(str);                                         \
353         if (! newvalue)                                                       \
354           MEMORY_ERROR;                                                       \
355         else                                                                  \
356           obj->FIELD = newvalue;                                              \
357       }                                                                       \
358       destroy_gom_ctxt(ctxt);                                                 \
359     }                                                                         \
360   }
361
362 #define DEFINE_DATE_CB(STRUCTTYPE,CB_NAME,FIELD)                              \
363   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
364   {                                                                           \
365     Gom_ctxt result = NULL;                                                   \
366     if (! parent)                                                             \
367       NO_CONTEXT;                                                             \
368     else {                                                                    \
369       struct STRUCTTYPE *obj                                                  \
370         = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
371       if (obj) {                                                              \
372         struct date_value dv = GEDCOM_DATE(parsed_value);                     \
373         obj->FIELD = gedcom_new_date_value(&dv);                              \
374         if (! obj->FIELD)                                                     \
375           MEMORY_ERROR;                                                       \
376         else                                                                  \
377           result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                       \
378       }                                                                       \
379     }                                                                         \
380     return (Gedcom_ctxt)result;                                               \
381   }
382
383 #define DEFINE_AGE_CB(STRUCTTYPE,CB_NAME,FIELD)                               \
384   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
385   {                                                                           \
386     Gom_ctxt result = NULL;                                                   \
387     if (! parent)                                                             \
388       NO_CONTEXT;                                                             \
389     else {                                                                    \
390       struct STRUCTTYPE *obj                                                  \
391         = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
392       if (obj) {                                                              \
393         struct age_value age = GEDCOM_AGE(parsed_value);                      \
394         obj->FIELD = gedcom_new_age_value(&age);                              \
395         if (! obj->FIELD)                                                     \
396           MEMORY_ERROR;                                                       \
397         else                                                                  \
398           result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                       \
399       }                                                                       \
400     }                                                                         \
401     return (Gedcom_ctxt)result;                                               \
402   }
403
404 #define DEFINE_XREF_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE)                  \
405   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
406   {                                                                           \
407     Gom_ctxt result = NULL;                                                   \
408     if (! parent)                                                             \
409       NO_CONTEXT;                                                             \
410     else {                                                                    \
411       struct STRUCTTYPE *obj                                                  \
412         = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
413       struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);                  \
414       if (! xr->object)                                                       \
415         xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string);         \
416       if (obj) {                                                              \
417         obj->FIELD = xr;                                                      \
418         result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                         \
419       }                                                                       \
420     }                                                                         \
421     return (Gedcom_ctxt)result;                                               \
422   }
423
424 #define DEFINE_XREF_LIST_CB(STRUCTTYPE,CB_NAME,FIELD,LINKSTRTYPE)             \
425   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
426   {                                                                           \
427     Gom_ctxt result = NULL;                                                   \
428     if (! parent)                                                             \
429       NO_CONTEXT;                                                             \
430     else {                                                                    \
431       struct STRUCTTYPE *obj                                                  \
432         = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
433       struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);                  \
434       struct xref_list *xrl;                                                  \
435       if (! xr->object)                                                       \
436         xr->object = (Gedcom_ctxt) MAKEFUNC(LINKSTRTYPE)(xr->string);         \
437       if (obj) {                                                              \
438         MAKE_CHAIN_ELT(xref_list, obj->FIELD, xrl);                           \
439         if (xrl) {                                                            \
440           xrl->xref = xr;                                                     \
441           result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                       \
442         }                                                                     \
443       }                                                                       \
444     }                                                                         \
445     return (Gedcom_ctxt)result;                                               \
446   }
447
448 #define DEFINE_NULL_CB(STRUCTTYPE,CB_NAME)                                    \
449   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
450   {                                                                           \
451     Gom_ctxt result = NULL;                                                   \
452     if (! parent)                                                             \
453       NO_CONTEXT;                                                             \
454     else {                                                                    \
455       struct STRUCTTYPE *obj                                                  \
456         = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                       \
457       if (obj)                                                                \
458         result = MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                         \
459     }                                                                         \
460     return (Gedcom_ctxt)result;                                               \
461   }
462
463
464
465 #endif /* __FUNC_TEMPLATE_H */