1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>Using the GEDCOM parser library</title>
4 <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"></head><body text="#000000" bgcolor="#ffffff" link="#000099" vlink="#990099" alink="#000099">
6 <h1 align="center">Using the GEDCOM parser library</h1>
12 <li><a href="#anchor">Overview</a></li>
13 <li><a href="#Error_handling">Error handling</a></li>
14 <li><a href="#Data_callback_mechanism">Data callback mechanism</a></li>
17 <li><a href="#Start_and_end_callbacks">Start and end callbacks</a></li>
18 <li><a href="#Default_callbacks">Default callbacks</a></li>
20 </ul><li><a href="#Other_API_functions">Other API functions</a></li>
23 <li><a href="#Debugging">Debugging</a></li>
24 <li><a href="#Error_treatment">Error treatment</a></li>
25 <li><a href="#Compatibility_mode">Compatibility mode</a></li>
28 <li><a href="#Converting_character_sets">Converting character sets</a></li>
29 <li><a href="#Support_for_configure.in">Support for configure.in</a><br>
32 <li><a href="interface.html">Interface details of the callback parser</a></li><li><a href="gom.html">C object model</a><br>
38 <hr width="100%" size="2">
39 <h2><a name="Overview"></a>Overview<br>
41 parser library provides two interfaces. At the one hand, it can be
42 used as a callback-based parser (comparable to the SAX interface of
43 XML); at the other hand, the parser can be used to convert the GEDCOM file
44 into an object model (comparable to the DOM interface of XML). It comes
48 <li>a library (<code>libgedcom.so</code>), to be linked in the
49 application program, which implements the callback parser</li>
50 <li>a header file (<code>gedcom.h</code>), to be used in the sources
51 of the application program</li>
52 <li>a header file (<code>gedcom-tags.h</code>) that is also installed,
53 but that is automatically included via <code>gedcom.h</code></li></ul>Additionally, if you want to use the GEDCOM C object model, the following should be used (note that <code>libgedcom.so</code> is also needed in this case, because the object model uses the callback parser internally):<br>
55 <li>a library (<code>libgedcom_gom.so</code>), to be linked in the application program, which implements the C object model</li>
56 <li>a header file (<code>gom.h</code>), to be used in the sources of the application program<br>
62 Next to these, there is also a data directory in <code>$PREFIX/share/gedcom-parse</code>
63 that contains some additional stuff, but which is not immediately
64 important at first. I'll leave the description of the data directory
67 The very simplest call of the gedcom callback parser is simply the following
68 piece of code (include of the <code>gedcom.h</code> header is assumed, as everywhere
71 <blockquote><code>int result;<br>
73 <b>gedcom_init</b>();<br>
75 result = <b>gedcom_parse_file</b>("myfamily.ged");<br>
77 Although this will not provide much information, one thing it does
78 is parse the entire file and return the result. The function returns
79 0 on success and 1 on failure. No other information is available
80 using this function only.<br>
82 Alternatively, programs using the C object model should use the following (in this case, the inclusion of both <code>gedcom.h</code> and <code>gom.h</code> is required):<br>
84 <blockquote><code>int result;<br>
86 <b>gedcom_init</b>();<br>
88 result = <b>gom_parse_file</b>("myfamily.ged");<br>
90 The call to <code>gom_parse_file</code> will build the C object model, which is then a complete representation of the GEDCOM file.<br>
92 No matter which of the interfaces you use, the call to <code>gedcom_init</code>() should be one of the first calls
93 in your program. The requirement is that it should come before the first
94 call to <code>iconv_open</code> (part of the generic character set conversion
95 feature) in the program, either by your program itself, or indirectly by
96 the library calls it makes. Practically, it should e.g. come before
97 any calls to any GTK functions, because GTK uses <code>iconv_open</code>
98 in its initialization.<br>
100 For the same reason it is also advised to put
101 the <code>-lgedcom</code> option
102 on the linking of the program as the last option, so that its initialization
103 code is run first. In the case of using the C object model, the linking
104 options should be: <code>-lgedcom_gom -lgedcom</code><br>
106 The next sections will refine this piece of code to be able to have
107 meaningful errors and the actual data that is in the file.<br>
109 <hr width="100%" size="2">
110 <h2><a name="Error_handling"></a>Error handling</h2>The library can be used in several different circumstances, both
111 terminal-based as GUI-based. Therefore, it leaves the actual display
112 of the error message up to the application. For this, the application
113 needs to register a callback before parsing the GEDCOM file, which will
114 be called by the library on errors, warnings and messages.<br>
116 A typical piece of code would be (<code>gom_parse_file</code> would be called in case the C object model is used):<br>
118 <blockquote><code>void <b>my_message_handler</b> (Gedcom_msg_type type,
124 <b>gedcom_set_message_handler</b>(my_message_handler);<br>
126 result = <b>gedcom_parse_file</b>("myfamily.ged");</code><br>
128 In the above piece of code, <code>my_message_handler</code> is the
129 callback that will be called for errors (<code>type=ERROR</code>), warnings
130 (<code>type=WARNING</code>) and messages (<code>type=MESSAGE</code>). The
131 callback must have the signature as in the example. For errors,
132 the <code> msg</code> passed to the callback will have the format:<br>
134 <blockquote><code>Error on line</code> <i><lineno></i>: <i><actual_message></i><br>
136 Note that the entire string will be properly internationalized, and
137 encoded in UTF-8 (<a href="encoding.html">Why UTF-8?</a>). Also,
138 no newline is appended, so that the application program can use it in any
139 way it wants. Warnings are similar, but use "Warning" instead of "Error".
140 Messages are plain text, without any prefix.<br>
142 With this in place, the resulting code will already show errors and
143 warnings produced by the parser, e.g. on the terminal if a simple <code>
144 printf</code> is used in the message handler.<br>
146 <hr width="100%" size="2">
147 <h2><a name="Data_callback_mechanism"></a>Data callback mechanism</h2>
148 The most important use of the parser is of course to get the data
149 out of the GEDCOM file. This section focuses on the callback mechanism (see <a href="gom.html">here</a> for the C object model). In fact, the mechanism involves two levels.<br>
151 The primary level is that each of the sections in a GEDCOM file is
152 notified to the application code via a "start element" callback and an
153 "end element" callback (much like in a SAX interface for XML), i.e. when
154 a line containing a certain tag is parsed, the "start element" callback
155 is called for that tag, and when all its subordinate lines with their
156 tags have been processed, the "end element" callback is called for the
157 original tag. Since GEDCOM is hierarchical, this results in properly
158 nested calls to appropriate "start element" and "end element" callbacks.<br>
160 However, it would be typical for a genealogy program to support only
161 a subset of the GEDCOM standard, certainly a program that is still under
162 development. Moreover, under GEDCOM it is allowed for an application
163 to define its own tags, which will typically not be supported by
164 another application. Still, in that case, data preservation is important;
165 it would hardly be accepted that information that is not understood by
166 a certain program is just removed.<br>
168 Therefore, the second level of callbacks involves a "default callback".
169 An application needs to subscribe to callbacks for tags it does support,
170 and need to provide a "default callback" which will be called for tags
171 it doesn't support. The application can then choose to just store
172 the information that comes via the default callback in plain textual format.<br>
174 After this introduction, let's see what the API looks like...<br>
177 <h3><a name="Start_and_end_callbacks"></a>Start and end callbacks</h3>
179 <h4><i>Callbacks for records</i> <br>
181 As a simple example, we will get some information from the header
182 of a GEDCOM file. First, have a look at the following piece of code:<br>
184 <blockquote><code>Gedcom_ctxt <b>my_header_start_cb</b> (Gedcom_rec rec,<br>
185 int level, <br>
186
187 Gedcom_val xref, <br>
188
189 char *tag, <br>
190
191 char *raw_value,<br>
192
193 int parsed_tag, <br>
194
195 Gedcom_val parsed_value)<br>
197 printf("The header starts\n");<br>
198 return (Gedcom_ctxt)1;<br>
201 void <b>my_header_end_cb</b> (Gedcom_rec rec, Gedcom_ctxt self)<br>
203 printf("The header ends, context is %d\n", (int)self);
204 /* context will print as "1" */<br>
208 <b>gedcom_subscribe_to_record</b>(REC_HEAD, my_header_start_cb,
209 my_header_end_cb);<br>
211 result = <b>gedcom_parse_file</b>("myfamily.ged");</code><br>
213 Using the <code>gedcom_subscribe_to_record</code> function, the
214 application requests to use the specified callbacks as start and end
215 callback. The end callback is optional: you can pass <code>NULL</code>
216 if you are not interested in the end callback. The identifiers
217 to use as first argument to the function (here <code>REC_HEAD</code>)
218 are described in the <a href="interface.html#Record_identifiers"> interface
219 details</a> . These are also passed as first argument in the callbacks (the <code>Gedcom_rec</code> argument).<br>
221 From the name of the function it becomes clear that this function
222 is specific to complete records. For the separate elements in records
223 there is another function, which we'll see shortly. Again, the callbacks
224 need to have the signatures as shown in the example.<br>
226 The <code>Gedcom_ctxt</code> type that is used as a result of the
227 start callback and as an argument to the end callback is vital for passing
228 context necessary for the application. This type is meant to be opaque;
229 in fact, it's a void pointer, so you can pass anything via it. The
230 important thing to know is that the context that the application returns
231 in the start callback will be passed in the end callback as an argument,
232 and as we will see shortly, also to all the directly subordinate elements
235 The <code>tag</code> is the GEDCOM tag in string format, the <code>parsed_tag</code>
236 is an integer, for which symbolic values are defined as <code>TAG_HEAD,</code>
237 <code>TAG_SOUR,</code> <code>TAG_DATA,</code> ... and <code>USERTAG
238 </code><code></code> for the application-specific tags. These values
239 are defined in the header <code>gedcom-tags.h</code> that is installed,
240 and included via <code> gedcom.h</code> (so no need to include <code>gedcom-tags.h</code>
243 The example passes a simple integer as context, but an application
244 could e.g. pass a <code>struct</code> (or an object in a C++ application)
245 that will contain the information for the header. In the end callback,
246 the application could then e.g. do some finalizing operations on the
247 <code> struct</code> to put it in its database.<br>
249 (Note that the <code>Gedcom_val</code> type for the <code>xref</code>
250 and <code>parsed_value</code> arguments was not discussed, see further
254 <h4><i>Callbacks for elements</i></h4>
255 We will now retrieve the SOUR field (the name of the program that
256 wrote the file) from the header:<br>
258 <blockquote><code>Gedcom_ctxt <b>my_header_source_start_cb</b>(Gedcom_elt elt,<br>
259
260 Gedcom_ctxt
262
263 int
264 level,<br>
265
266 char*
267 tag,<br>
268
269 char*
270 raw_value,<br>
271
272 int
273 parsed_tag,<br>
274
275 Gedcom_val
276 parsed_value)<br>
278 char *source = GEDCOM_STRING(parsed_value);<br>
279 printf("This file was written by %s\n", source);<br>
280 return parent;<br>
283 void <b>my_header_source_end_cb</b>(Gedcom_elt elt,<br>
284 Gedcom_ctxt parent,<br>
285
286 Gedcom_ctxt self,<br>
287
288 Gedcom_val parsed_value)<br>
290 printf("End of the source description\n");<br>
294 <b>gedcom_subscribe_to_element</b>(ELT_HEAD_SOUR,<br>
295
296 my_header_source_start_cb,<br>
297
298 my_header_source_end_cb);<br>
300 result = <b>gedcom_parse_file</b>("myfamily.ged");</code><br>
302 The subscription mechanism for elements is similar, only the signatures
303 of the callbacks differ. The signature for the start callback shows
304 that the context of the parent line (here e.g. the <code>struct</code>
305 that describes the header) is passed to this start callback. The
306 callback itself returns here in this example the same context, but this
307 can be its own context object of course. The end callback is called
308 with both the context of the parent and the context of itself, which in this
309 example will be the same. Again, the list of identifiers to use as
310 a first argument for the subscription function are detailed in the <a href="interface.html#Element_identifiers"> interface details</a> . Again, these are passed as first argument in the callback (the <code>Gedcom_elt</code> argument).<br>
312 If we look at the other arguments of the start callback, we see the
313 level number (the initial number of the line in the GEDCOM file), the tag
314 (e.g. "SOUR"), and then a raw value, a parsed tag and a parsed value. The
315 raw value is just the raw string that occurs as value on the line next
316 to the tag (in UTF-8 encoding). The parsed value is the meaningful
317 value that is parsed from that raw string. The parsed tag is described
318 in the section for record callbacks above.<br>
320 The <code>Gedcom_val</code> type is meant to be an opaque type. The
321 only thing that needs to be known about it is that it can contain specific
322 data types, which have to be retrieved from it using pre-defined macros.
323 These data types are described in the <a href="interface.html#Gedcom_val_types"> interface details</a>.
326 Some extra notes:<br>
330 <li>The <code>Gedcom_val</code> argument of the end callback
331 is currently not used. It is there for future enhancements.</li>
332 <li>There are also two <code>Gedcom_val</code> arguments
333 in the start callback for records. The first one (<code>xref</code>
334 ) contains the <code>xref_value</code> corresponding to the cross-reference
335 (or <code>NULL</code> if there isn't one), the second one (<code>parsed_value</code>
336 ) contains the value that is parsed from the <code>raw_value</code>. See
337 the <a href="interface.html#Record_identifiers">interface details</a>
344 <h3><a name="Default_callbacks"></a>Default callbacks<br>
346 As described above, an application doesn't always implement the entire
347 GEDCOM spec, and application-specific tags may have been added by other
348 applications. To preserve this extra data anyway, a default callback
349 can be registered by the application, as in the following example:<br>
351 <blockquote><code>void <b>my_default_cb</b> (Gedcom_elt elt, Gedcom_ctxt parent, int level,
352 char* tag, char* raw_value, int parsed_tag)<br>
358 <b>gedcom_set_default_callback</b>(my_default_cb);<br>
360 result = <b>gedcom_parse_file</b>("myfamily.ged");</code><br>
362 This callback has a similar signature as the previous ones,
363 but it doesn't contain a parsed value. However, it does contain the
364 parent context, that was returned by the application for the most specific
365 containing tag that the application supported.<br>
367 Suppose e.g. that this callback is called for some tags in the header
368 that are specific to some other application, then our application could
369 make sure that the parent context contains the struct or object that represents
370 the header, and use the default callback here to add the level, tag and
371 raw_value as plain text in a member of that struct or object, thus preserving
372 the information. The application can then write this out when the
373 data is saved again in a GEDCOM file. To make it more specific, consider
374 the following example:<br>
376 <blockquote><code>struct header {<br>
377 char* source;<br>
379 char* extra_text;<br>
382 Gedcom_ctxt my_header_start_cb(Gedcom_rec rec, int level, Gedcom_val xref, char* tag,
384
385 int parsed_tag, Gedcom_val parsed_value)<br>
387 struct header head = my_make_header_struct();<br>
388 return (Gedcom_ctxt)head;<br>
391 void my_default_cb(Gedcom_elt elt, Gedcom_ctxt parent, int level, char* tag, char*
392 raw_value, int parsed_tag)<br>
394 struct header head = (struct header)parent;<br>
395 my_header_add_to_extra_text(head, level, tag, raw_value);<br>
398 gedcom_set_default_callback(my_default_cb);<br>
399 gedcom_subscribe_to_record(REC_HEAD, my_header_start, NULL);<br>
401 result = gedcom_parse_file(filename);</code><br>
403 Note that the default callback will be called for any tag that isn't
404 specifically subscribed upon by the application, and can thus be called
405 in various contexts. For simplicity, the example above doesn't take
406 this into account (the <code>parent</code> could be of different
407 types, depending on the context).<br>
409 Note also that the default callback is not called when the parent context
410 is <code>NULL</code><code></code>. This is e.g. the case if none
411 of the "upper" tags has been subscribed upon.<br>
414 <hr width="100%" size="2">
416 <h2><a name="Other_API_functions"></a>Other API functions<br>
419 Although the above describes the basic interface of the gedcom parser, there
420 are some other functions that allow to customize the behaviour of the library.
421 These will be explained in the current section.<br>
424 <h3><a name="Debugging"></a>Debugging</h3>
425 The library can generate various debugging output, not only from itself,
426 but also the debugging output generated by the yacc parser. By default,
427 no debugging output is generated, but this can be customized using the
428 following function:<br>
431 <blockquote><code>void <b>gedcom_set_debug_level</b> (int level, FILE*
432 trace_output)</code><br>
434 The <code>level</code> can be one of the following values:<br>
438 <li>0: no debugging information (this is the
440 <li>1: only debugging information from libgedcom
442 <li>2: debugging information from libgedcom
447 If the <code>trace_output</code> is <code>NULL</code>, debugging information
448 will be written to <code>stderr</code>, otherwise the given file handle
449 is used (which must be open).<br>
453 <h3><a name="Error_treatment"></a>Error treatment</h3>
454 One of the previous sections already described the callback to be
455 registered to get error messages. The library also allows to customize
456 what happens on an error, using the following function:<br>
459 <blockquote><code>void <b>gedcom_set_error_handling</b> (Gedcom_err_mech
460 mechanism)</code><br>
462 The <code>mechanism</code> can be one of:<br>
466 <li><code>IMMED_FAIL</code>: immediately fail
467 the parsing on an error (this is the default)</li>
468 <li><code>DEFER_FAIL</code>: continue parsing
469 after an error, but return a failure code eventually</li>
470 <li><code>IGNORE_ERRORS</code>: continue parsing
471 after an error, return success always</li>
475 This doesn't influence the generation of error or warning messages,
476 only the behaviour of the parser and its return code.<br>
480 <h3><a name="Compatibility_mode"></a>Compatibility mode<br>
482 Applications are not necessarily true to the GEDCOM spec (or use a
483 different version than 5.5). The intention is that the library is
484 resilient to this, and goes in compatibility mode for files written by specific
485 programs (detected via the HEAD.SOUR tag). This compatibility mode
486 can be enabled and disabled via the following function:<br>
489 <blockquote><code>void <b>gedcom_set_compat_handling</b> (int enable_compat)</code><br>
491 The argument can be:<br>
495 <li>0: disable compatibility mode</li>
496 <li>1: allow compatibility mode (this is the
502 Currently, there is a beginning for compatibility for ftree and Lifelines (3.0.2).<br>
504 <hr width="100%" size="2">
505 <h2><a name="Converting_character_sets"></a>Converting character sets</h2>
506 All strings passed by the GEDCOM parser to the application are in UTF-8
507 encoding. Typically, an application needs to convert this to something
508 else to be able to display it.<br>
510 The most common case is that the output character set is controlled by
511 the <code>locale</code> mechanism (i.e. via the <code>LANG</code>, <code>
512 LC_ALL</code> or <code>LC_CTYPE</code> environment variables), which also
513 controls the <code>gettext</code> mechanism in the application. <br>
517 The source distribution of <code>
518 gedcom-parse</code> contains an example implementation (<code>utf8-locale.c</code>
519 and <code> utf8-locale.h</code> in the "t" subdirectory of the top directory).
520 Feel free to use it in your source code (it is not part of the library,
521 and it isn't installed anywhere, so you need to take over the source and
522 header file in your application). <br>
524 Its interface is:<br>
527 <pre><code>char *<b>convert_utf8_to_locale</b> (char *input, int *conv_failures);<br>char *<b>convert_locale_to_utf8</b> (char *input);<br></code></pre>
529 Both functions return a pointer to a static buffer that is overwritten
530 on each call. To function properly, the application must first set
531 the locale using the <code>setlocale</code> function (the second step detailed
532 below). All other steps given below, including setting up and closing
533 down the conversion handles, are transparantly handled by the two functions.
536 If you pass a pointer to an integer to the first function, it will be
537 set to the number of conversion failures, i.e. characters that couldn't
538 be converted; you can also just pass <code>NULL</code> if you are not interested
539 (note that usually, the interesting information is just whether there <i>
540 were</i> conversion failures or not, which is then given by the integer
541 being bigger than zero or not). The second function doesn't need this,
542 because any locale can be converted to UTF-8.<br>
544 You can change the "?" that is output for characters that can't be converted
545 to any string you want, using the following function before the conversion
549 <pre><code>void <b>convert_set_unknown</b> (const char *unknown);</code></pre>
552 If you want to have your own functions for it instead of this example
553 implementation, the following steps need to be taken by the application
554 (more detailed info can be found in the info file of the GNU libc library
555 in the "Generic Charset Conversion" section under "Character Set Handling"
556 or online <a href="http://www.gnu.org/manual/glibc-2.2.3/html_chapter/libc_6.html#SEC99">
560 <li>inclusion of some headers:</li>
566 <pre><code>#include <locale.h> /* for setlocale */<br>#include <langinfo.h> /* for nl_langinfo */<br>#include <iconv.h> /* for iconv_* functions */<br></code></pre>
571 <li>set the program's current locale to what
572 the user configured in the environment:</li>
578 <pre><code>setlocale(LC_ALL, "");</code><br></pre>
583 <li>open a conversion handle for conversion
584 from UTF-8 to the character set of the current locale (once for the entire
591 <pre><code>iconv_t iconv_handle;<br>...<br>iconv_handle = iconv_open(nl_langinfo(CODESET), "UTF-8");</code><br>if (iconv_handle == (iconv_t) -1)<br> /* signal an error */<br></pre>
596 <li>then, every string can be converted
597 using the following:</li>
603 <pre><code>/* char* in_buf is the input buffer, size_t in_len is its length */<br>/* char* out_buf is the output buffer, size_t out_len is its length */<br><br>size_t nconv;<br>char *in_ptr = in_buf;<br>char *out_ptr = out_buf;<br>nconv = iconv(iconv_handle, &in_ptr, &in_len, &out_ptr, &out_len);</code></pre>
607 <blockquote>If the output buffer is not big enough, <code>iconv</code> will
608 return -1 and set <code>errno</code> to <code>E2BIG</code>. Also,
609 the <code>in_ptr</code> and <code>out_ptr</code> will point just after
610 the last successfully converted character in the respective buffers, and
611 the <code> in_len</code> and <code>out_len</code> will be updated to show
612 the remaining lengths. There can be two strategies here:<br>
615 <li>Make sure from the beginning
616 that the output buffer is big enough. However, it's difficult to find
617 an absolute maximum length in advance, even given the length of the input
621 <li>Do the conversion in several
622 steps, growing the output buffer each time to make more space, and calling
623 <code>iconv</code> consecutively until the conversion is complete.
624 This is the preferred way (a function could be written to encapsulate
628 Another error case is when the conversion was unsuccessful (if one of
629 the characters can't be represented in the target character set). The
630 <code> iconv</code> function will then also return -1 and set <code>errno</code>
631 to <code>EILSEQ</code>; the <code>in_ptr</code> will point to the character
632 that couldn't be converted. In that case, again two strategies are
636 <li>Just fail the conversion,
637 and show an error. This is not very user friendly, of course.<br>
640 <li>Skip over the character that
641 can't be converted and append a "?" to the output buffer, then call <code>
642 iconv</code> again. Skipping over a UTF-8 character is fairly simple,
643 as follows from the <a href="http://www.cl.cam.ac.uk/%7Emgk25/unicode.html#utf-8">encoding rules</a>
651 <li>if the first byte is in
652 binary 0xxxxxxx, then the character is only one byte long, just skip over
656 <li>if the first byte is in
657 binary 11xxxxxx, then skip over that byte and all bytes 10xxxxxx that follow.<br>
666 <li>eventually, the conversion
667 handle needs to be closed (when the program exits):<br>
674 <pre><code>iconv_close(iconv_handle);<br></code></pre>
677 The example implementation
678 mentioned above grows the output buffer dynamically and outputs "?" for characters
679 that can't be converted.<br>
682 <hr width="100%" size="2">
684 <h2><a name="Support_for_configure.in"></a>Support for configure.in</h2>
685 Programs using the GEDCOM parser library and using autoconf to configure
686 their sources can use the following statements in configure.in (the example
687 is checking for gedcom-parse, version 1.34):<br>
689 <blockquote><code>AC_CHECK_LIB(gedcom, gedcom_parse_file,,<br>
690 AC_MSG_ERROR(Cannot
691 find libgedcom: Please install gedcom-parse))<br>
692 AC_MSG_CHECKING(for libgedcom version)<br>
694 #include <stdio.h><br>
695 #include <stdlib.h><br>
696 #include <gedcom.h><br>
700 if (GEDCOM_PARSE_VERSION >= 1034) exit(0);<br>
703 ac_gedcom_version_ok='yes',<br>
704 ac_gedcom_version_ok='no',<br>
705 ac_gedcom_version_ok='no')<br>
706 if test "$ac_gedcom_version_ok" = 'yes' ; then<br>
707 AC_MSG_RESULT(ok)<br>
709 AC_MSG_RESULT(not ok)<br>
710 AC_MSG_ERROR(You need at least version 1.34 of gedcom-parse)<br>
713 There are three preprocessor symbols defined for version checks in the
717 <li><code>GEDCOM_PARSE_VERSION_MAJOR</code></li>
718 <li><code>GEDCOM_PARSE_VERSION_MINOR</code></li>
719 <li><code>GEDCOM_PARSE_VERSION</code><br>
723 The last one is equal to <code>(GEDCOM_PARSE_VERSION_MAJOR * 1000) + GEDCOM_PARSE_VERSION_MINOR.</code><br>
725 <hr width="100%" size="2">
727 <pre><font size="-1">$Id$<br>$Name$</font><br></pre>