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