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