A bit of refactoring...
[gedcom-parse.git] / t / src / standalone.c
1 /* Test program for the Gedcom library.
2    Copyright (C) 2001, 2002 The Genes Development Team
3    This file is part of the Gedcom parser library.
4    Contributed by Peter Verthez <Peter.Verthez@advalvas.be>, 2001.
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 "gedcom.h"
25 #include "output.h"
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <locale.h>
30 #include <errno.h>
31 #include <iconv.h>
32 #include "utf8-locale.h"
33
34 #define BOGUS_FILE_NAME "Makefile.am"
35
36 void show_help ()
37 {
38   printf("gedcom-parse test program for libgedcom\n\n");
39   printf("Usage:  testgedcom [options] file\n");
40   printf("Options:\n");
41   printf("  -h    Show this help text\n");
42   printf("  -nc   Disable compatibility mode\n");
43   printf("  -fi   Fail immediately on errors\n");
44   printf("  -fd   Deferred fail on errors, but parse completely\n");
45   printf("  -fn   No fail on errors\n");
46   printf("  -dg   Debug setting: only libgedcom debug messages\n");
47   printf("  -da   Debug setting: libgedcom + yacc debug messages\n");
48   printf("  -2    Run the test parse 2 times instead of once\n");
49   printf("  -3    Run the test parse 3 times instead of once\n");
50   printf("  -b    Parse a bogus file before parsing the main file\n");
51   printf("  -q    No output to standard output\n");
52 }
53
54 Gedcom_ctxt header_start(Gedcom_rec rec, int level, Gedcom_val xref, char *tag,
55                          char *raw_value, int tag_value,
56                          Gedcom_val parsed_value)
57 {
58   output(1, "Header start\n");
59   return (Gedcom_ctxt)1;
60 }
61
62 void header_end(Gedcom_rec rec, Gedcom_ctxt self)
63 {
64   output(1, "Header end, context is %d\n", (int)self);
65 }
66
67 char family_xreftags[100][255];
68 int  family_nr = 1;
69
70 Gedcom_ctxt family_start(Gedcom_rec rec, int level, Gedcom_val xref, char *tag,
71                          char *raw_value, int tag_value,
72                          Gedcom_val parsed_value)
73 {
74   struct xref_value *xr = GEDCOM_XREF_PTR(xref);
75   output(1, "Family start, xref is %s\n", xr->string);
76   strcpy(family_xreftags[family_nr], xr->string);
77   xr->object = (Gedcom_ctxt)family_nr;
78   return (Gedcom_ctxt)(family_nr++);
79 }
80
81 Gedcom_ctxt rec_start(Gedcom_rec rec, int level, Gedcom_val xref, char *tag,
82                       char *raw_value, int tag_value,
83                       Gedcom_val parsed_value)
84 {
85   char* xref_str = NULL;
86   if (! GEDCOM_IS_NULL(xref))
87     xref_str = GEDCOM_XREF_PTR(xref)->string;
88   output(1, "Rec %s start, xref is %s\n", tag, xref_str);
89   return (Gedcom_ctxt)tag_value;
90 }
91
92 Gedcom_ctxt note_start(Gedcom_rec rec, int level, Gedcom_val xref, char *tag,
93                        char *raw_value, int tag_value,
94                        Gedcom_val parsed_value)
95 {
96   output(1, "== %d %s (%d) %s (xref is %s)\n",
97          level, tag, tag_value, GEDCOM_STRING(parsed_value),
98          GEDCOM_XREF_PTR(xref)->string);
99   return (Gedcom_ctxt)tag_value;
100 }
101
102 void family_end(Gedcom_rec rec, Gedcom_ctxt self)
103 {
104   output(1, "Family end, xref is %s\n", family_xreftags[(int)self]);
105 }
106
107 Gedcom_ctxt submit_start(Gedcom_rec rec, int level, Gedcom_val xref, char *tag,
108                          char *raw_value, int tag_value,
109                          Gedcom_val parsed_value)
110 {
111   output(1, "Submitter, xref is %s\n", GEDCOM_XREF_PTR(xref)->string);
112   return (Gedcom_ctxt)10000;
113 }
114
115 Gedcom_ctxt source_start(Gedcom_elt elt, Gedcom_ctxt parent, int level,
116                          char *tag, char* raw_value,
117                          int tag_value, Gedcom_val parsed_value)
118 {
119   Gedcom_ctxt self = (Gedcom_ctxt)((int) parent + 1000);
120   output(1, "Source is %s (ctxt is %d, parent is %d)\n",
121          GEDCOM_STRING(parsed_value), (int) self, (int) parent);
122   return self;
123 }
124
125 void source_end(Gedcom_elt elt, Gedcom_ctxt parent, Gedcom_ctxt self,
126                 Gedcom_val parsed_value)
127 {
128   output(1, "Source context %d in parent %d\n", (int)self, (int)parent);
129 }
130
131 Gedcom_ctxt date_start(Gedcom_elt elt, Gedcom_ctxt parent, int level,
132                        char *tag, char* raw_value,
133                        int tag_value, Gedcom_val parsed_value)
134 {
135   struct date_value dv;
136   Gedcom_ctxt self = (Gedcom_ctxt)((int) parent + 1000);
137   dv = GEDCOM_DATE(parsed_value);
138   output(1, "Contents of the date_value:\n");
139   output(1, "  raw value: %s\n", raw_value);
140   output(1, "  type: %d\n", dv.type);
141   output(1, "  date1:\n");
142   output(1, "    calendar type: %d\n", dv.date1.cal);
143   output(1, "    day: %s\n", dv.date1.day_str);
144   output(1, "    month: %s\n", dv.date1.month_str);
145   output(1, "    year: %s\n", dv.date1.year_str);
146   output(1, "    date type: %d\n", dv.date1.type);
147   output(1, "    sdn1: %ld\n", dv.date1.sdn1);
148   output(1, "    sdn2: %ld\n", dv.date1.sdn2);
149   output(1, "  date2:\n");
150   output(1, "    calendar type: %d\n", dv.date2.cal);
151   output(1, "    day: %s\n", dv.date2.day_str);
152   output(1, "    month: %s\n", dv.date2.month_str);
153   output(1, "    year: %s\n", dv.date2.year_str);
154   output(1, "    date type: %d\n", dv.date2.type);
155   output(1, "    sdn1: %ld\n", dv.date2.sdn1);
156   output(1, "    sdn2: %ld\n", dv.date2.sdn2);
157   output(1, "  phrase: %s\n", dv.phrase);
158   return self;
159 }
160
161 Gedcom_ctxt age_start(Gedcom_elt elt, Gedcom_ctxt parent, int level,
162                       char *tag, char *raw_value,
163                       int tag_value, Gedcom_val parsed_value)
164 {
165   struct age_value age;
166   Gedcom_ctxt self = (Gedcom_ctxt)((int) parent + 1000);
167   age = GEDCOM_AGE(parsed_value);
168   output(1, "Contents of the age_value:\n");
169   output(1, "  raw value: %s\n", raw_value);
170   output(1, "  type: %d\n", age.type);
171   output(1, "  modifier: %d\n", age.mod);
172   output(1, "  years: %d\n", age.years);
173   output(1, "  months: %d\n", age.months);
174   output(1, "  days: %d\n", age.days);
175   output(1, "  phrase: %s\n", age.phrase);
176   return self;
177 }
178
179 void default_cb(Gedcom_elt elt, Gedcom_ctxt ctxt, int level, char *tag,
180                 char *raw_value, int tag_value)
181 {
182   char   *converted = NULL;
183   int    conv_fails = 0;
184   if (raw_value)
185     converted = convert_utf8_to_locale(raw_value, &conv_fails);
186   output(0, "== %d %s (%d) %s (ctxt is %d, conversion failures: %d)\n",
187          level, tag, tag_value, converted, (int)ctxt, conv_fails);
188 }
189
190 void subscribe_callbacks()
191 {
192   gedcom_subscribe_to_record(REC_HEAD, header_start, header_end);
193   gedcom_subscribe_to_record(REC_FAM,  family_start, family_end);
194   gedcom_subscribe_to_record(REC_INDI, rec_start, NULL);
195   gedcom_subscribe_to_record(REC_OBJE, rec_start, NULL);
196   gedcom_subscribe_to_record(REC_NOTE, note_start, NULL);
197   gedcom_subscribe_to_record(REC_REPO, rec_start, NULL);
198   gedcom_subscribe_to_record(REC_SOUR, rec_start, NULL);
199   gedcom_subscribe_to_record(REC_SUBN, rec_start, NULL);
200   gedcom_subscribe_to_record(REC_SUBM, submit_start, NULL);
201   gedcom_subscribe_to_record(REC_USER, rec_start, NULL);
202   gedcom_subscribe_to_element(ELT_HEAD_SOUR, source_start, source_end);
203   gedcom_subscribe_to_element(ELT_SOUR_DATA_EVEN_DATE,
204                               date_start, NULL);
205   gedcom_subscribe_to_element(ELT_SUB_EVT_DATE, date_start, NULL);
206   gedcom_subscribe_to_element(ELT_SUB_FAM_EVT_AGE, age_start, NULL);
207 }
208
209 void gedcom_message_handler(Gedcom_msg_type type, char *msg)
210 {
211   if (type == MESSAGE)
212     output(1, "MESSAGE: ");
213   else if (type == WARNING)
214     output(1, "WARNING: ");
215   else if (type == ERROR)
216     output(1, "ERROR: ");
217   output(1, "%s\n", msg);
218 }
219
220 int main(int argc, char* argv[])
221 {
222   Gedcom_err_mech mech = IMMED_FAIL;
223   int compat_enabled = 1;
224   int debug_level = 0;
225   int run_times   = 1;
226   int bogus       = 0;
227   int result      = 0;
228   char* file_name = NULL;
229
230   if (argc > 1) {
231     int i;
232     for (i=1; i<argc; i++) {
233       if (!strncmp(argv[i], "-da", 4))
234         debug_level = 2;
235       else if (!strncmp(argv[i], "-dg", 4))
236         debug_level = 1;
237       else if (!strncmp(argv[i], "-fi", 4))
238         mech = IMMED_FAIL;
239       else if (!strncmp(argv[i], "-fd", 4))
240         mech = DEFER_FAIL;
241       else if (!strncmp(argv[i], "-fn", 4))
242         mech = IGNORE_ERRORS;
243       else if (!strncmp(argv[i], "-nc", 4))
244         compat_enabled = 0;
245       else if (!strncmp(argv[i], "-h", 3)) {
246         show_help();
247         exit(1);
248       }
249       else if (!strncmp(argv[i], "-2", 3)) {
250         run_times = 2;
251       }
252       else if (!strncmp(argv[i], "-3", 3)) {
253         run_times = 3;
254       }
255       else if (!strncmp(argv[i], "-b", 3)) {
256         bogus = 1;
257       }
258       else if (!strncmp(argv[i], "-q", 3)) {
259         output_set_quiet(1);
260       }
261       else if (strncmp(argv[i], "-", 1)) {
262         file_name = argv[i];
263         break;
264       }
265       else {
266         printf ("Unrecognized option: %s\n", argv[i]);
267         show_help();
268         exit(1);
269       }
270     }
271   }
272   
273   if (!file_name) {
274     printf("No file name given\n");
275     show_help();
276     exit(1);
277   }
278
279   gedcom_init();
280   setlocale(LC_ALL, "");
281   gedcom_set_debug_level(debug_level, NULL);
282   gedcom_set_compat_handling(compat_enabled);
283   gedcom_set_error_handling(mech);
284   gedcom_set_message_handler(gedcom_message_handler);
285   gedcom_set_default_callback(default_cb);
286   
287   subscribe_callbacks();
288   output_open();
289   if (bogus) {
290     output(0, "\n=== Parsing bogus file %s\n", BOGUS_FILE_NAME);
291     gedcom_parse_file(BOGUS_FILE_NAME);
292   }
293   while (run_times-- > 0) {
294     output(0, "\n=== Parsing file %s\n", file_name);
295     result |= gedcom_parse_file(file_name);
296   }
297   if (result == 0) {
298     output(1, "Parse succeeded\n");
299   }
300   else {
301     output(1, "Parse failed\n");
302   }
303   output_close();
304   return result;
305 }