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