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