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