First check-in of gedcom object model.
[gedcom-parse.git] / gom / gom_internal.h
1 /* General header for the Gedcom object model.
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 __GOM_INTERNAL_H
25 #define __GOM_INTERNAL_H
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <libintl.h>
30 #include "gom.h"
31 #include "gedcom.h"
32 #ifdef WITH_DMALLOC
33 #include <dmalloc.h>
34 #endif
35       
36 #define _(string) gettext(string)
37 #define N_(string) (string)
38
39 typedef enum {
40   T_NULL,
41   
42   T_header, T_submission, T_submitter, T_family, T_individual,
43   T_multimedia, T_note, T_repository, T_source, T_user_rec,
44   
45   T_address, T_event, T_place, T_source_citation, T_text,
46   T_note_sub, T_multimedia_link, T_lds_event, T_user_ref_number,
47   T_change_date, T_personal_name, T_family_link, T_pedigree,
48   T_association, T_source_event, T_source_description
49 } OBJ_TYPE;
50
51 struct Gom_ctxt_struct {
52   int ctxt_type;
53   OBJ_TYPE obj_type;
54   void* ctxt_ptr;
55 };
56
57 typedef struct Gom_ctxt_struct *Gom_ctxt;
58
59 Gom_ctxt make_gom_ctxt(int ctxt_type, OBJ_TYPE obj_type, void *ctxt_ptr);
60 void destroy_gom_ctxt(Gom_ctxt ctxt);
61 void gom_cast_error(char* file, int line, OBJ_TYPE expected, OBJ_TYPE found);
62 void gom_unexpected_context(char* file, int line, OBJ_TYPE found);
63
64 #define MAKE_GOM_CTXT(CTXT_TYPE, STRUCTTYPE, CTXT_PTR)                        \
65   make_gom_ctxt(CTXT_TYPE, T_ ## STRUCTTYPE, CTXT_PTR)
66
67 #define SAFE_CTXT_CAST(STRUCTTYPE, VAL)                                       \
68   (((VAL)->obj_type == T_ ## STRUCTTYPE) ?                                    \
69    (VAL)->ctxt_ptr :                                                          \
70    (gom_cast_error(__FILE__, __LINE__, T_ ## STRUCTTYPE, (VAL)->obj_type),    \
71     (VAL)->ctxt_ptr))
72
73 #define SAFE_FREE(PTR)                                                        \
74   if (PTR) {                                                                  \
75     free(PTR);                                                                \
76     PTR = NULL;                                                               \
77   }
78
79 #define UNEXPECTED_CONTEXT(CTXT_TYPE)                                         \
80   gom_unexpected_context(__FILE__, __LINE__, CTXT_TYPE)
81
82 void def_rec_end(Gedcom_rec rec, Gedcom_ctxt self);
83 void def_elt_end(Gedcom_elt elt, Gedcom_ctxt parent, Gedcom_ctxt self,
84                  Gedcom_val parsed_value);
85 void set_xref_type(struct xref_value *xr, char* str);
86
87 typedef enum {
88   WITHOUT_NL,
89   WITH_NL
90 } NL_TYPE;
91
92 char* concat_strings(NL_TYPE type, char *str1, const char *str2);
93 struct date_value* dup_date(struct date_value dv);
94 struct age_value*  dup_age(struct age_value age);
95
96 /* Doubly-linked list, but last rec->next is NULL (doesn't go to first rec) */
97 #define LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                             \
98   {                                                                           \
99     struct STRUCTTYPE *_local_obj = VAL;                                      \
100     if (! FIRSTVAL) {                                                         \
101       VAL->next = NULL;                                                       \
102       VAL->previous = _local_obj;                                             \
103       FIRSTVAL = VAL;                                                         \
104     }                                                                         \
105     else {                                                                    \
106       VAL->next = NULL;                                                       \
107       FIRSTVAL->previous->next = VAL;                                         \
108       VAL->previous = FIRSTVAL->previous;                                     \
109       FIRSTVAL->previous = VAL;                                               \
110     }                                                                         \
111   }
112
113 #define MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                             \
114   {                                                                           \
115     VAL = (struct STRUCTTYPE*) malloc(sizeof(struct STRUCTTYPE));             \
116     memset (VAL, 0, sizeof(struct STRUCTTYPE));                               \
117     LINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                                 \
118   }
119
120 void NULL_DESTROY(void* anything);
121
122 #define DESTROY_CHAIN_ELTS(STRUCTTYPE, FIRSTVAL, DESTROYFUNC)                 \
123   {                                                                           \
124     if (FIRSTVAL) {                                                           \
125       struct STRUCTTYPE *runner, *next;                                       \
126       runner = FIRSTVAL;                                                      \
127       while (runner) {                                                        \
128         next = runner->next;                                                  \
129         DESTROYFUNC(runner);                                                  \
130         SAFE_FREE(runner);                                                    \
131         runner = next;                                                        \
132       }                                                                       \
133     }                                                                         \
134   }
135
136 #define _REC_PARAMS_ Gedcom_rec rec, int level, Gedcom_val xref, char *tag,   \
137                      char *raw_value, int parsed_tag, Gedcom_val parsed_value
138
139 #define _ELT_PARAMS_ Gedcom_elt elt, Gedcom_ctxt parent, int level, char *tag,\
140                      char *raw_value, int parsed_tag, Gedcom_val parsed_value
141
142 #define REC_CB(STRUCTTYPE,CB_NAME,FUNC)                                       \
143   Gedcom_ctxt CB_NAME(_REC_PARAMS_)                                           \
144   {                                                                           \
145     struct xref_value* xr = GEDCOM_XREF_PTR(xref);                            \
146     if (! xr->object)                                                         \
147       xr->object = (Gedcom_ctxt) FUNC(xr->string);                            \
148     return (Gedcom_ctxt) MAKE_GOM_CTXT(rec, STRUCTTYPE, xr->object);          \
149   }
150
151 #define GET_REC_BY_XREF(STRUCTTYPE,XREF_TYPE,FUNC_NAME)                       \
152   struct STRUCTTYPE *FUNC_NAME(char *xrefstr)                                 \
153   {                                                                           \
154     struct xref_value* xr = gedcom_get_by_xref(xrefstr);                      \
155     if (xr && (xr->type == XREF_TYPE) && xr->object)                          \
156       return (struct STRUCTTYPE*)(xr->object);                                \
157     else                                                                      \
158       return NULL;                                                            \
159   }
160
161 #define STRING_CB(STRUCTTYPE,CB_NAME,FIELD)                                   \
162   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
163   {                                                                           \
164     char *str = GEDCOM_STRING(parsed_value);                                  \
165     struct STRUCTTYPE *obj                                                    \
166       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
167     if (obj) obj->FIELD = strdup(str);                                        \
168     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
169   }
170
171 #define DATE_CB(STRUCTTYPE,CB_NAME,FIELD)                                     \
172   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
173   {                                                                           \
174     struct date_value dv = GEDCOM_DATE(parsed_value);                         \
175     struct STRUCTTYPE *obj                                                    \
176       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
177     if (obj) obj->FIELD = dup_date(dv);                                       \
178     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
179   }
180
181 #define AGE_CB(STRUCTTYPE,CB_NAME,FIELD)                                      \
182   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
183   {                                                                           \
184     struct age_value age = GEDCOM_AGE(parsed_value);                          \
185     struct STRUCTTYPE *obj                                                    \
186       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
187     if (obj) obj->FIELD = dup_age(age);                                       \
188     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
189   }
190
191 #define XREF_CB(STRUCTTYPE,CB_NAME,FIELD,FUNC)                                \
192   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
193   {                                                                           \
194     struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);                    \
195     struct STRUCTTYPE *obj                                                    \
196       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
197     if (! xr->object)                                                         \
198       xr->object = (Gedcom_ctxt) FUNC(xr->string);                            \
199     if (obj) obj->FIELD = xr;                                                 \
200     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
201   }
202
203 #define XREF_LIST_CB(STRUCTTYPE,CB_NAME,FIELD,FUNC)                           \
204   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
205   {                                                                           \
206     struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);                    \
207     struct STRUCTTYPE *obj                                                    \
208       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
209     struct xref_list *xrl;                                                    \
210     if (! xr->object)                                                         \
211       xr->object = (Gedcom_ctxt) FUNC(xr->string);                            \
212     MAKE_CHAIN_ELT(xref_list, obj->FIELD, xrl);                               \
213     xrl->xref = xr;                                                           \
214     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
215   }
216
217 #define NULL_CB(STRUCTTYPE,CB_NAME)                                           \
218   Gedcom_ctxt CB_NAME(_ELT_PARAMS_)                                           \
219   {                                                                           \
220     struct STRUCTTYPE *obj                                                    \
221       = SAFE_CTXT_CAST(STRUCTTYPE, (Gom_ctxt)parent);                         \
222     return (Gedcom_ctxt) MAKE_GOM_CTXT(elt, STRUCTTYPE, obj);                 \
223   }
224
225 #endif /* __GOM_INTERNAL_H */