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