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