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