b34d59e1e5fcefefa12abf8b22b31a41a2914295
[gedcom-parse.git] / gom / gom.c
1 /* Main file for building 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 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include "gedcom.h"
28 #include "header.h"
29 #include "submitter.h"
30 #include "submission.h"
31 #include "family.h"
32 #include "individual.h"
33 #include "multimedia.h"
34 #include "note.h"
35 #include "repository.h"
36 #include "source.h"
37 #include "user_rec.h"
38 #include "address.h"
39 #include "event.h"
40 #include "place.h"
41 #include "source_citation.h"
42 #include "multimedia_link.h"
43 #include "note_sub.h"
44 #include "lds_event.h"
45 #include "user_ref.h"
46 #include "change_date.h"
47 #include "personal_name.h"
48 #include "family_link.h"
49 #include "association.h"
50 #include "source_event.h"
51 #include "source_description.h"
52 #include "gom.h"
53 #include "gom_internal.h"
54
55 const char* ctxt_names[] =
56 {
57   "NULL",
58   
59   "header", "submission", "submitter", "family", "individual",
60   "multimedia", "note", "repository", "source", "user_rec",
61   
62   "address", "event", "place", "source_citation", "text",
63   "note_sub", "multimedia_link", "lds_event", "user_ref_number",
64   "change_date", "personal_name", "family_link", "pedigree",
65   "association", "source_event", "source_description"
66 };
67
68 void gom_default_callback (Gedcom_elt elt, Gedcom_ctxt parent, int level,
69                            char* tag, char* raw_value, int parsed_tag);
70
71 void gom_cleanup()
72 {
73   header_cleanup();
74   submission_cleanup();
75   families_cleanup();
76   individuals_cleanup();
77   multimedias_cleanup();
78   notes_cleanup();
79   repositories_cleanup();
80   sources_cleanup();
81   submitters_cleanup();
82   user_recs_cleanup();
83 }
84
85 void subscribe_all()
86 {
87   gedcom_set_default_callback(gom_default_callback);
88   header_subscribe();
89   submission_subscribe();
90   family_subscribe();
91   individual_subscribe();
92   multimedia_subscribe();
93   note_subscribe();
94   repository_subscribe();
95   source_subscribe();
96   submitter_subscribe();
97   user_rec_subscribe();
98   
99   address_subscribe();
100   event_subscribe();
101   place_subscribe();
102   citation_subscribe();
103   note_sub_subscribe();
104   multimedia_link_subscribe();
105   lds_event_subscribe();
106   user_ref_subscribe();
107   change_date_subscribe();
108   name_subscribe();
109   family_link_subscribe();
110   association_subscribe();
111   source_event_subscribe();
112   source_description_subscribe();
113
114   if (atexit(gom_cleanup) != 0) {
115     gedcom_warning(_("Could not register gom cleanup function"));
116   }
117 }
118
119 int gom_active = 0;
120
121 int gom_parse_file(const char* file_name)
122 {
123   if (gom_active) {
124     gom_cleanup();
125   }
126   else {
127     subscribe_all();
128   }
129   gom_active = 1;
130   gedcom_set_compat_options(0);
131   return gedcom_parse_file(file_name);
132 }
133
134 int gom_new_model()
135 {
136   if (gom_active) {
137     gom_cleanup();
138   }
139   else {
140     subscribe_all();
141   }
142   gom_active = 1;
143   return gedcom_new_model();
144 }
145
146 int gom_write_file(const char* file_name, int *total_conv_fails)
147 {
148   Gedcom_write_hndl hndl;
149   int result = 1;
150
151   hndl = gedcom_write_open(file_name);
152   if (hndl) {
153     result = write_header(hndl);
154     result |= write_submission(hndl);
155     result |= write_submitters(hndl);
156     result |= write_individuals(hndl);
157     result |= write_families(hndl);
158     result |= write_multimedia_recs(hndl);
159     result |= write_notes(hndl);
160     result |= write_repositories(hndl);
161     result |= write_sources(hndl);
162     result |= write_user_recs(hndl);
163     result |= gedcom_write_close(hndl, total_conv_fails);
164   }
165
166   return result;
167 }
168
169 int gom_write_xref_list(Gedcom_write_hndl hndl,
170                         Gedcom_elt elt, int tag, int parent_rec_or_elt,
171                         struct xref_list* val)
172 {
173   int result = 0;
174   struct xref_list* xrl;
175   for (xrl = val; xrl; xrl = xrl->next) {
176     result |= gedcom_write_element_xref(hndl, elt, tag, parent_rec_or_elt,
177                                         xrl->xref);
178   }
179   return result;
180 }
181
182 Gom_ctxt make_gom_ctxt(int ctxt_type, OBJ_TYPE obj_type, void *ctxt_ptr)
183 {
184   Gom_ctxt ctxt   = (Gom_ctxt)malloc(sizeof(struct Gom_ctxt_struct));
185   if (! ctxt)
186     MEMORY_ERROR;
187   else {
188     ctxt->ctxt_type = ctxt_type;
189     ctxt->obj_type  = obj_type;
190     ctxt->ctxt_ptr  = ctxt_ptr;
191   }
192   return ctxt;
193 }
194
195 void NULL_DESTROY(void* anything UNUSED)
196 {
197 }
198
199 void destroy_gom_ctxt(Gom_ctxt ctxt)
200 {
201   SAFE_FREE(ctxt);
202 }
203
204 void gom_cast_error(const char* file, int line,
205                     OBJ_TYPE expected, OBJ_TYPE found)
206 {
207   const char* expected_name = "<out-of-bounds>";
208   const char* found_name    = "<out-of-bounds>";
209   if (expected < T_LAST)
210     expected_name = ctxt_names[expected];
211   if (found < T_LAST)
212     found_name = ctxt_names[found];
213   fprintf(stderr,
214           "Wrong gom ctxt cast at %s, line %d: expected %s, found %s\n",
215           file, line, expected_name, found_name);
216   abort();
217 }
218
219 void gom_mem_error(const char *filename, int line)
220 {
221   gedcom_error(_("Could not allocate memory at %s, %d"), filename, line);
222 }
223
224 void gom_xref_already_in_use(const char *xrefstr)
225 {
226   gedcom_error(_("Cross-reference key '%s' is already in use"), xrefstr);
227 }
228
229 void gom_unexpected_context(const char* file, int line, OBJ_TYPE found)
230 {
231   const char* found_name    = "<out-of-bounds>";
232   if (found < T_LAST)
233     found_name = ctxt_names[found];
234   gedcom_warning(_("Internal error: Unexpected context at %s, line %d: %s"),
235                  file, line, found_name);
236 }
237
238 void gom_no_context(const char* file, int line)
239 {
240   gedcom_warning(_("Internal error: No context at %s, line %d"),
241                  file, line);
242 }
243
244 void gom_move_error(const char* type)
245 {
246   gedcom_warning(_("Could not move struct of type %s"), type);
247 }
248
249 void gom_find_error(const char* type)
250 {
251   gedcom_warning(_("Could not find struct of type %s in chain"), type);
252 }
253
254 void gom_default_callback (Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED,
255                            int level, char* tag, char* raw_value,
256                            int parsed_tag UNUSED)
257 {
258   gedcom_warning(_("Data loss in import: \"%d %s %s\""),
259                  level, tag, raw_value);
260 }
261
262 void def_rec_end(Gedcom_rec rec UNUSED, Gedcom_ctxt self,
263                  Gedcom_val parsed_value UNUSED)
264 {
265   Gom_ctxt ctxt = (Gom_ctxt)self;
266   destroy_gom_ctxt(ctxt);
267 }
268
269 void def_elt_end(Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED,
270                  Gedcom_ctxt self, Gedcom_val parsed_value UNUSED)
271 {
272   Gom_ctxt ctxt = (Gom_ctxt)self;
273   destroy_gom_ctxt(ctxt);
274 }
275
276 void set_xref_type(struct xref_value* xr, const char *str)
277 {
278   if (!strcasecmp(str, "FAM"))
279     xr->type = XREF_FAM;
280   else if (!strcasecmp(str, "INDI"))
281     xr->type = XREF_INDI;
282   else if (!strcasecmp(str, "NOTE"))
283     xr->type = XREF_NOTE;
284   else if (!strcasecmp(str, "OBJE"))
285     xr->type = XREF_OBJE;
286   else if (!strcasecmp(str, "REPO"))
287     xr->type = XREF_REPO;
288   else if (!strcasecmp(str, "SOUR"))
289     xr->type = XREF_SOUR;
290   else if (!strcasecmp(str, "SUBM"))
291     xr->type = XREF_SUBM;
292   else if (!strcasecmp(str, "SUBN"))
293     xr->type = XREF_SUBN;
294   else
295     xr->type = XREF_ANY;
296 }