8bb5bb69433065923cec61990f970c5b7ee0a58a
[gedcom-parse.git] / gedcom / gedcom.y
1 /* Parser for Gedcom.
2    Copyright (C) 2001 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 /* WARNING: THIS PARSER RELIES HEAVILY ON SOME FEATURES OF BISON.
25    DON'T TRY TO USE IT WITH YACC, IT WON'T WORK...
26 */
27
28 /* Design of the parser:
29    ---------------------
30    In general, a GEDCOM file contains records, each consisting of a line
31    (which we'll call a section), hierarchically containing other lines
32    (subsections of the section).
33
34    This means that in general we have:
35
36      A 'record' is a 'section' (sect) containing 'subsections' (subs)
37      Each 'subsection' (sub) is again a specific 'section' (sect)
38
39    In parser notation, this means:
40
41      record : sect
42
43      sect   : <some prefix> subs <some suffix>
44
45      subs   : <empty> | subs sub
46
47      sub    : sect_a | sect_b | ...
48
49    This pattern is repeated throughout the parser for the different types of
50    sections.
51    
52
53    Cardinality of the subsections:
54    -------------------------------
55    Note that in the above, the order of the subsections is of no importance.
56    Indeed, this is the case in the GEDCOM grammar.  However, this also makes
57    it difficult to check whether there are not too many subsections of a
58    specific type, or whether a mandatory subsection is indeed there.
59
60    Suppose there is a section A that can contain 0 or 1 B section and
61    2 C sections.
62
63    This can be expressed in parser notation as follows:
64
65      A    : CC | BCC | CBC | CCB
66
67    So, cardinality is indeed expressable.  However, as the number of subsection
68    types and the limits grow bigger (and even theoretically limitless), listing
69    all possible permutations becomes quickly unfeasible.
70
71    Much simpler is to say:
72
73      A    : subs
74      subs : <empty> | subs sub
75      sub  : B | C
76
77    and then check the cardinality in the semantic actions, which is the
78    solution chosen in the parser below, using the following macros:
79
80     - OPEN(<parent>)
81          Make a new context for the <parent> tag to count child tags in
82          
83     - OCCUR2(<child>, <min>, <max>)
84          Express that the <child> tag should occur at least <min> times and
85          at most <max> tags within its parent
86
87          What this actually does is the following.  It increments the counter
88          for that tag and then checks whether the maximum is exceeded.  If so,
89          then a parser error is produced.  The minimum is not actually checked
90          by this macro, but it makes the statements more declarative.
91
92     - OCCUR1(<child>, <min>)
93          Express that the <child> tag should occur at least <min> times within
94          its parent (no upper limit)
95
96          Actually, this only increments the counter for the tag, but it looks
97          very like the previous macro.
98
99          If the minimum is 0, it is not necessary to express this constraint.
100
101     - CHECKn(<child1>, ..., <childn>)
102          This closes the context for the parent tag and checks whether the
103          given <child> tags did effectively occur within the parent (i.e.
104          these are the tags that were mandatory).
105
106          Since the <min> values above are always 0 or 1 in GEDCOM, this is
107          sufficient.  All sub-tags that declare a minimum of 1 in the OCCUR
108          macros should be listed in this macro here.
109
110          The macros CHECK0 to CHECK4 are defined like this (the first one
111          has no arguments and is only used to close the parent context; note
112          that this is necessary for correct functioning).
113
114    Example of usage:
115
116      Only sections that have subsections need to use these macros.  This can
117      be done like this (the OPEN and CHECK macros are used as mid-rule
118      actions around the subsections):
119
120        head_sect : OPEN DELIM TAG_HEAD
121                    { OPEN(HEAD) }
122                    head_subs
123                    { CHECK1(SOUR) }
124                    CLOSE { <semantic actions> }
125                   
126        head_subs : <empty>
127                  | head_subs head_sub
128                  ;
129
130        head_sub  : head_sour_sect  { OCCUR2(SOUR, 1, 1) }
131                  | head_dest_sect  { OCCUR2(DEST, 0, 1) }
132                  | head_date_sect  { OCCUR2(DATE, 0, 1) }
133                  ;
134 */
135
136 /* General notes:
137
138    - The syntax analysis doesn't handle the contents of the line values;
139      this is done in the semantic analysis.
140
141  */
142
143 %{
144 #include "gedcom_internal.h"
145 #include "multilex.h"
146 #include "encoding.h"
147 #include "interface.h"
148 #include "date.h"
149
150 int  count_level    = 0;
151 int  fail           = 0;
152 int  compat_enabled = 1;
153 int  gedcom_high_level_debug = 0; 
154 int  compatibility  = 0; 
155 Gedcom_err_mech error_mechanism = IMMED_FAIL;
156 Gedcom_val_struct val; 
157  
158 char line_item_buf[MAXGEDCLINELEN * UTF_FACTOR + 1];
159 char *line_item_buf_ptr;
160
161 enum _COMPAT {
162   C_FTREE = 0x01
163 };
164
165 /* These are defined at the bottom of the file */ 
166 void push_countarray();
167 void set_parenttag(char* tag);
168 char* get_parenttag(); 
169 void set_parentctxt(Gedcom_ctxt ctxt);
170 Gedcom_ctxt get_parentctxt();
171 void pop_countarray();
172 int  count_tag(int tag);
173 int  check_occurrence(int tag);
174 void set_compatibility(char* program);
175 int  compat_mode(int flags); 
176
177 #define CLEAR_BUFFER(BUF)                                                     \
178      memset(BUF, 0, sizeof(BUF));
179  
180 #define HANDLE_ERROR                                                          \
181      { if (error_mechanism == IMMED_FAIL) {                                   \
182          YYABORT;                                                             \
183        }                                                                      \
184        else if (error_mechanism == DEFER_FAIL) {                              \
185          yyerrok; fail = 1;                                                   \
186        }                                                                      \
187        else if (error_mechanism == IGNORE_ERRORS) {                           \
188          yyerrok;                                                             \
189        }                                                                      \
190      }
191 #define START(PARENTTAG,PARENTCTXT)                                           \
192      { ++count_level;                                                         \
193        set_parenttag(#PARENTTAG);                                             \
194        set_parentctxt(PARENTCTXT);                                            \
195        push_countarray();                                                     \
196      }
197 #define PARENT                                                              \
198      get_parentctxt()
199 #define CHK(TAG)                                                              \
200      { if (!check_occurrence(TAG_##TAG)) {                                    \
201          char* parenttag = get_parenttag();                                   \
202          gedcom_error(_("The tag '%s' is mandatory within '%s', but missing"),\
203                       #TAG, parenttag);                                       \
204          HANDLE_ERROR;                                                        \
205        }                                                                      \
206      }
207 #define POP                                                                   \
208      { pop_countarray();                                                      \
209        --count_level;                                                         \
210      }
211 #define CHECK0 POP; 
212 #define CHECK1(TAG1) { CHK(TAG1); POP; }
213 #define CHECK2(TAG1,TAG2)                                                     \
214      { CHK(TAG1); CHK(TAG2); POP; }
215 #define CHECK3(TAG1,TAG2,TAG3)                                                \
216      { CHK(TAG1); CHK(TAG2); CHK(TAG3); POP; }
217 #define CHECK4(TAG1,TAG2,TAG3,TAG4)                                           \
218      { CHK(TAG1); CHK(TAG2); CHK(TAG3); CHK(TAG4); POP; } 
219 #define OCCUR1(CHILDTAG, MIN) { count_tag(TAG_##CHILDTAG); } 
220 #define OCCUR2(CHILDTAG, MIN, MAX)                                            \
221      { int num = count_tag(TAG_##CHILDTAG);                                   \
222        if (num > MAX) {                                                       \
223          char* parenttag = get_parenttag();                                   \
224          gedcom_error(_("The tag '%s' can maximally occur %d time(s) within '%s'"),                                                                          \
225                       #CHILDTAG, MAX, parenttag);                             \
226          HANDLE_ERROR;                                                        \
227        }                                                                      \
228      }
229 #define INVALID_TAG(CHILDTAG)                                                 \
230      { char* parenttag = get_parenttag();                                     \
231        gedcom_error(_("The tag '%s' is not a valid tag within '%s'"),         \
232                     CHILDTAG, parenttag);                                     \
233        HANDLE_ERROR;                                                          \
234      }
235 #define INVALID_TOP_TAG(CHILDTAG)                                             \
236      { gedcom_error(_("The tag '%s' is not a valid top-level tag"),           \
237                     CHILDTAG); \
238        HANDLE_ERROR; \
239      }
240
241 %}
242
243 %union {
244   int  number;
245   char *string;
246   Gedcom_ctxt ctxt;
247 }
248
249 %token_table
250 %expect 300
251
252 %token <string> BADTOKEN
253 %token <number> OPEN
254 %token <string> CLOSE
255 %token <string> ESCAPE
256 %token <string> DELIM
257 %token <string> ANYCHAR
258 %token <string> POINTER
259 %token <string> USERTAG
260 %token <string> TAG_ABBR
261 %token <string> TAG_ADDR
262 %token <string> TAG_ADR1
263 %token <string> TAG_ADR2
264 %token <string> TAG_ADOP
265 %token <string> TAG_AFN
266 %token <string> TAG_AGE
267 %token <string> TAG_AGNC
268 %token <string> TAG_ALIA
269 %token <string> TAG_ANCE
270 %token <string> TAG_ANCI
271 %token <string> TAG_ANUL
272 %token <string> TAG_ASSO
273 %token <string> TAG_AUTH
274 %token <string> TAG_BAPL
275 %token <string> TAG_BAPM
276 %token <string> TAG_BARM
277 %token <string> TAG_BASM
278 %token <string> TAG_BIRT
279 %token <string> TAG_BLES
280 %token <string> TAG_BLOB
281 %token <string> TAG_BURI
282 %token <string> TAG_CALN
283 %token <string> TAG_CAST
284 %token <string> TAG_CAUS
285 %token <string> TAG_CENS
286 %token <string> TAG_CHAN
287 %token <string> TAG_CHAR
288 %token <string> TAG_CHIL
289 %token <string> TAG_CHR
290 %token <string> TAG_CHRA
291 %token <string> TAG_CITY
292 %token <string> TAG_CONC
293 %token <string> TAG_CONF
294 %token <string> TAG_CONL
295 %token <string> TAG_CONT
296 %token <string> TAG_COPR
297 %token <string> TAG_CORP
298 %token <string> TAG_CREM
299 %token <string> TAG_CTRY
300 %token <string> TAG_DATA
301 %token <string> TAG_DATE
302 %token <string> TAG_DEAT
303 %token <string> TAG_DESC
304 %token <string> TAG_DESI
305 %token <string> TAG_DEST
306 %token <string> TAG_DIV
307 %token <string> TAG_DIVF
308 %token <string> TAG_DSCR
309 %token <string> TAG_EDUC
310 %token <string> TAG_EMIG
311 %token <string> TAG_ENDL
312 %token <string> TAG_ENGA
313 %token <string> TAG_EVEN
314 %token <string> TAG_FAM
315 %token <string> TAG_FAMC
316 %token <string> TAG_FAMF
317 %token <string> TAG_FAMS
318 %token <string> TAG_FCOM
319 %token <string> TAG_FILE
320 %token <string> TAG_FORM
321 %token <string> TAG_GEDC
322 %token <string> TAG_GIVN
323 %token <string> TAG_GRAD
324 %token <string> TAG_HEAD
325 %token <string> TAG_HUSB
326 %token <string> TAG_IDNO
327 %token <string> TAG_IMMI
328 %token <string> TAG_INDI
329 %token <string> TAG_LANG
330 %token <string> TAG_LEGA
331 %token <string> TAG_MARB
332 %token <string> TAG_MARC
333 %token <string> TAG_MARL
334 %token <string> TAG_MARR
335 %token <string> TAG_MARS
336 %token <string> TAG_MEDI
337 %token <string> TAG_NAME
338 %token <string> TAG_NATI
339 %token <string> TAG_NATU
340 %token <string> TAG_NCHI
341 %token <string> TAG_NICK
342 %token <string> TAG_NMR
343 %token <string> TAG_NOTE
344 %token <string> TAG_NPFX
345 %token <string> TAG_NSFX
346 %token <string> TAG_OBJE
347 %token <string> TAG_OCCU
348 %token <string> TAG_ORDI
349 %token <string> TAG_ORDN
350 %token <string> TAG_PAGE
351 %token <string> TAG_PEDI
352 %token <string> TAG_PHON
353 %token <string> TAG_PLAC
354 %token <string> TAG_POST
355 %token <string> TAG_PROB
356 %token <string> TAG_PROP
357 %token <string> TAG_PUBL
358 %token <string> TAG_QUAY
359 %token <string> TAG_REFN
360 %token <string> TAG_RELA
361 %token <string> TAG_RELI
362 %token <string> TAG_REPO
363 %token <string> TAG_RESI
364 %token <string> TAG_RESN
365 %token <string> TAG_RETI
366 %token <string> TAG_RFN
367 %token <string> TAG_RIN
368 %token <string> TAG_ROLE
369 %token <string> TAG_SEX
370 %token <string> TAG_SLGC
371 %token <string> TAG_SLGS
372 %token <string> TAG_SOUR
373 %token <string> TAG_SPFX
374 %token <string> TAG_SSN
375 %token <string> TAG_STAE
376 %token <string> TAG_STAT
377 %token <string> TAG_SUBM
378 %token <string> TAG_SUBN
379 %token <string> TAG_SURN
380 %token <string> TAG_TEMP
381 %token <string> TAG_TEXT
382 %token <string> TAG_TIME
383 %token <string> TAG_TITL
384 %token <string> TAG_TRLR
385 %token <string> TAG_TYPE
386 %token <string> TAG_VERS
387 %token <string> TAG_WIFE
388 %token <string> TAG_WILL
389
390 %type <string> anystdtag
391 %type <string> anytoptag
392 %type <string> line_item
393 %type <string> line_value
394 %type <string> mand_line_item
395 %type <string> mand_pointer
396 %type <string> note_line_item
397 %type <string> anychar
398 %type <string> opt_xref
399 %type <string> opt_value
400 %type <ctxt> head_sect
401
402 %%
403
404 file        : head_sect records trlr_sect
405                { if (fail == 1) YYABORT; }
406             ;
407
408 records     : /* empty */
409             | records record
410             ;
411
412 record      : fam_rec
413             | indiv_rec
414             | multim_rec
415             | note_rec
416             | repos_rec
417             | source_rec
418             | submis_rec
419             | submit_rec
420             | no_std_rec
421             ;
422
423 /*********************************************************************/
424 /**** Header                                                      ****/
425 /*********************************************************************/
426 head_sect    : OPEN DELIM TAG_HEAD
427                { $<ctxt>$ = start_record(REC_HEAD, $1, NULL, $3);
428                  START(HEAD, $<ctxt>$) }
429                head_subs
430                { if (compat_mode(C_FTREE))
431                    CHECK3(SOUR, GEDC, CHAR)
432                  else
433                    CHECK4(SOUR, SUBM, GEDC, CHAR)
434                }
435                CLOSE
436                { end_record(REC_HEAD, $<ctxt>4); }
437              ;
438
439 head_subs    : /* empty */
440              | head_subs head_sub
441              ;
442
443 head_sub     : head_sour_sect  { OCCUR2(SOUR, 1, 1) }
444              | head_dest_sect  { OCCUR2(DEST, 0, 1) }
445              | head_date_sect  { OCCUR2(DATE, 0, 1) }
446              | head_subm_sect  { OCCUR2(SUBM, 1, 1) }
447              | head_subn_sect  { OCCUR2(SUBN, 0, 1) }
448              | head_file_sect  { OCCUR2(FILE, 0, 1) }
449              | head_copr_sect  { OCCUR2(COPR, 0, 1) }
450              | head_gedc_sect  { OCCUR2(GEDC, 1, 1) }
451              | head_char_sect  { OCCUR2(CHAR, 1, 1) }
452              | head_lang_sect  { OCCUR2(LANG, 0, 1) }
453              | head_plac_sect  { OCCUR2(PLAC, 0, 1) }
454              | head_note_sect  { OCCUR2(NOTE, 0, 1) }
455              | no_std_sub
456              ;
457
458 /* HEAD.SOUR */
459 head_sour_sect : OPEN DELIM TAG_SOUR mand_line_item 
460                  { set_compatibility($4);
461                    $<ctxt>$ = start_element(ELT_HEAD_SOUR, PARENT,
462                                             $1, $3, $4,
463                                             GEDCOM_MAKE_STRING($4));
464                    START(SOUR, $<ctxt>$)
465                  }
466                  head_sour_subs
467                  { CHECK0 }
468                  CLOSE
469                  { end_element(ELT_HEAD_SOUR, PARENT, $<ctxt>5, NULL); }
470                ;
471
472 head_sour_subs : /* empty */
473                | head_sour_subs head_sour_sub
474                ;
475
476 head_sour_sub : head_sour_vers_sect  { OCCUR2(VERS, 0, 1) }
477               | head_sour_name_sect  { OCCUR2(NAME, 0, 1) }
478               | head_sour_corp_sect  { OCCUR2(CORP, 0, 1) } 
479               | head_sour_data_sect  { OCCUR2(DATA, 0, 1) }
480               | no_std_sub
481               ;
482
483 head_sour_vers_sect : OPEN DELIM TAG_VERS mand_line_item
484                       { $<ctxt>$ = start_element(ELT_HEAD_SOUR_VERS, PARENT,
485                                                  $1, $3, $4,
486                                                  GEDCOM_MAKE_STRING($4));
487                         START(VERS, $<ctxt>$)
488                       }
489                       no_std_subs
490                       { CHECK0 }
491                       CLOSE
492                       { end_element(ELT_HEAD_SOUR_VERS,
493                                     PARENT, $<ctxt>5, NULL);
494                       }
495                     ;
496 head_sour_name_sect : OPEN DELIM TAG_NAME mand_line_item
497                       { $<ctxt>$ = start_element(ELT_HEAD_SOUR_NAME, PARENT,
498                                                  $1, $3, $4,
499                                                  GEDCOM_MAKE_STRING($4));
500                         START(NAME, $<ctxt>$)
501                       }
502                       no_std_subs
503                       { CHECK0 }
504                       CLOSE
505                       { end_element(ELT_HEAD_SOUR_NAME,
506                                     PARENT, $<ctxt>5, NULL);
507                       }
508                     ;
509 head_sour_corp_sect : OPEN DELIM TAG_CORP mand_line_item 
510                       { $<ctxt>$ = start_element(ELT_HEAD_SOUR_CORP, PARENT,
511                                                  $1, $3, $4, 
512                                                  GEDCOM_MAKE_STRING($4));
513                         START(CORP, $<ctxt>$)
514                       }
515                       head_sour_corp_subs
516                       { CHECK0 }
517                       CLOSE
518                       { end_element(ELT_HEAD_SOUR_CORP,
519                                     PARENT, $<ctxt>5, NULL);
520                       }
521                     ;
522
523 head_sour_corp_subs : /* empty */
524                     | head_sour_corp_subs head_sour_corp_sub
525                     ;
526
527 head_sour_corp_sub : addr_struc_sub  /* 0:1 */
528                    | no_std_sub
529                    ;
530
531 head_sour_data_sect : OPEN DELIM TAG_DATA mand_line_item 
532                       { $<ctxt>$ = start_element(ELT_HEAD_SOUR_DATA, PARENT,
533                                                  $1, $3, $4, 
534                                                  GEDCOM_MAKE_STRING($4));
535                         START(DATA, $<ctxt>$)
536                       }
537                       head_sour_data_subs
538                       { CHECK0 }
539                       CLOSE
540                       { end_element(ELT_HEAD_SOUR_DATA,
541                                     PARENT, $<ctxt>5, NULL);
542                       }
543                     ;
544
545 head_sour_data_subs : /* empty */
546                     | head_sour_data_subs head_sour_data_sub
547                     ;
548
549 head_sour_data_sub : head_sour_data_date_sect  { OCCUR2(DATE, 0, 1) }
550                    | head_sour_data_copr_sect  { OCCUR2(COPR, 0, 1) }
551                    | no_std_sub
552                    ;
553
554 head_sour_data_date_sect : OPEN DELIM TAG_DATE mand_line_item
555                            { struct date_value dv = gedcom_parse_date($4);
556                              $<ctxt>$ = start_element(ELT_HEAD_SOUR_DATA_DATE,
557                                                       PARENT, $1, $3, $4, 
558                                                       GEDCOM_MAKE_DATE(dv));
559                              START(DATE, $<ctxt>$)
560                            }
561                            no_std_subs
562                            { CHECK0 }
563                            CLOSE
564                            { end_element(ELT_HEAD_SOUR_DATA_DATE,
565                                          PARENT, $<ctxt>5, NULL);
566                            }
567                          ;
568 head_sour_data_copr_sect : OPEN DELIM TAG_COPR mand_line_item
569                            { $<ctxt>$ = start_element(ELT_HEAD_SOUR_DATA_COPR,
570                                                       PARENT, $1, $3, $4, 
571                                                       GEDCOM_MAKE_STRING($4));
572                              START(COPR, $<ctxt>$)
573                            }
574                            no_std_subs
575                            { CHECK0 }
576                            CLOSE
577                            { end_element(ELT_HEAD_SOUR_DATA_COPR,
578                                          PARENT, $<ctxt>5, NULL);
579                            }
580                          ;
581
582 /* HEAD.DEST */
583 head_dest_sect : OPEN DELIM TAG_DEST mand_line_item
584                  { $<ctxt>$ = start_element(ELT_HEAD_DEST,
585                                             PARENT, $1, $3, $4, 
586                                             GEDCOM_MAKE_STRING($4));
587                    START(DEST, $<ctxt>$)
588                  }
589                  no_std_subs
590                  { CHECK0 }
591                  CLOSE
592                  { end_element(ELT_HEAD_DEST,
593                                PARENT, $<ctxt>5, NULL);
594                  }
595                ;
596
597 /* HEAD.DATE */
598 head_date_sect : OPEN DELIM TAG_DATE mand_line_item 
599                  { struct date_value dv = gedcom_parse_date($4);
600                    $<ctxt>$ = start_element(ELT_HEAD_DATE,
601                                             PARENT, $1, $3, $4, 
602                                             GEDCOM_MAKE_DATE(dv));
603                    START(DATE, $<ctxt>$)
604                  }
605                  head_date_subs
606                  { CHECK0 }
607                  CLOSE
608                  { end_element(ELT_HEAD_DATE,
609                                PARENT, $<ctxt>5, NULL);
610                  }
611                ;
612
613 head_date_subs : /* empty */
614                | head_date_subs head_date_sub
615                ;
616
617 head_date_sub  : head_date_time_sect  { OCCUR2(TIME, 0, 1) }
618                | no_std_sub
619                ;
620
621 head_date_time_sect : OPEN DELIM TAG_TIME mand_line_item
622                       { $<ctxt>$ = start_element(ELT_HEAD_DATE_TIME,
623                                                  PARENT, $1, $3, $4, 
624                                                  GEDCOM_MAKE_STRING($4));
625                         START(TIME, $<ctxt>$)
626                       }
627                       no_std_subs
628                       { CHECK0 }
629                       CLOSE
630                       { end_element(ELT_HEAD_DATE_TIME,
631                                     PARENT, $<ctxt>5, NULL);
632                       }
633                     ;
634
635 /* HEAD.SUBM */
636 head_subm_sect : OPEN DELIM TAG_SUBM mand_pointer
637                  { $<ctxt>$ = start_element(ELT_HEAD_SUBM,
638                                             PARENT, $1, $3, $4, 
639                                             GEDCOM_MAKE_STRING($4));
640                    START(SUBM, $<ctxt>$)
641                  }
642                  no_std_subs
643                  { CHECK0 }
644                  CLOSE
645                  { end_element(ELT_HEAD_SUBM,
646                                PARENT, $<ctxt>5, NULL);
647                  }
648                ;
649 /* HEAD.SUBN */
650 head_subn_sect : OPEN DELIM TAG_SUBN mand_pointer 
651                  { $<ctxt>$ = start_element(ELT_HEAD_SUBN,
652                                             PARENT, $1, $3, $4, 
653                                             GEDCOM_MAKE_STRING($4));
654                    START(SUBN, $<ctxt>$)
655                  }
656                  no_std_subs
657                  { CHECK0 }
658                  CLOSE
659                  { end_element(ELT_HEAD_SUBN,
660                                PARENT, $<ctxt>5, NULL);
661                  }
662                ;
663 /* HEAD.FILE */
664 head_file_sect : OPEN DELIM TAG_FILE mand_line_item 
665                  { $<ctxt>$ = start_element(ELT_HEAD_FILE,
666                                             PARENT, $1, $3, $4, 
667                                             GEDCOM_MAKE_STRING($4));
668                    START(FILE, $<ctxt>$)
669                  }
670                  no_std_subs
671                  { CHECK0 }
672                  CLOSE
673                  { end_element(ELT_HEAD_FILE, PARENT, $<ctxt>5, NULL);
674                  }
675                ;
676 /* HEAD.COPR */
677 head_copr_sect : OPEN DELIM TAG_COPR mand_line_item 
678                  { $<ctxt>$ = start_element(ELT_HEAD_COPR,
679                                             PARENT, $1, $3, $4, 
680                                             GEDCOM_MAKE_STRING($4));
681                    START(COPR, $<ctxt>$)
682                  }
683                  no_std_subs
684                  { CHECK0 }
685                  CLOSE
686                  { end_element(ELT_HEAD_COPR, PARENT, $<ctxt>5, NULL);
687                  }
688                ;
689 /* HEAD.GEDC */
690 head_gedc_sect : OPEN DELIM TAG_GEDC
691                  { $<ctxt>$ = start_element(ELT_HEAD_GEDC,
692                                             PARENT, $1, $3, NULL, NULL);
693                    START(GEDC, $<ctxt>$)
694                  }
695                  head_gedc_subs
696                  { CHECK2(VERS, FORM) }
697                  CLOSE
698                  { end_element(ELT_HEAD_GEDC, PARENT, $<ctxt>4, NULL);
699                  }
700                ;
701
702 head_gedc_subs : /* empty */
703                | head_gedc_subs head_gedc_sub
704                ;
705
706 head_gedc_sub  : head_gedc_vers_sect  { OCCUR2(VERS, 1, 1) }
707                | head_gedc_form_sect  { OCCUR2(FORM, 1, 1) }
708                | no_std_sub
709                ;
710 head_gedc_vers_sect : OPEN DELIM TAG_VERS mand_line_item  
711                       { $<ctxt>$ = start_element(ELT_HEAD_GEDC_VERS,
712                                                  PARENT, $1, $3, $4, 
713                                                  GEDCOM_MAKE_STRING($4));
714                         START(VERS, $<ctxt>$)
715                       }
716                       no_std_subs
717                       { CHECK0 }
718                       CLOSE
719                       { end_element(ELT_HEAD_GEDC_VERS,
720                                     PARENT, $<ctxt>5, NULL);
721                       }
722                     ;
723 head_gedc_form_sect : OPEN DELIM TAG_FORM mand_line_item   
724                       { $<ctxt>$ = start_element(ELT_HEAD_GEDC_FORM,
725                                                  PARENT, $1, $3, $4, 
726                                                  GEDCOM_MAKE_STRING($4));
727                         START(FORM, $<ctxt>$)
728                       }
729                       no_std_subs
730                       { CHECK0 }
731                       CLOSE
732                       { end_element(ELT_HEAD_GEDC_FORM,
733                                     PARENT, $<ctxt>5, NULL);
734                       }
735                     ;
736
737 /* HEAD.CHAR */
738 head_char_sect : OPEN DELIM TAG_CHAR mand_line_item 
739                  { if (open_conv_to_internal($4) == 0) YYERROR;
740                    $<ctxt>$ = start_element(ELT_HEAD_CHAR,
741                                             PARENT, $1, $3, $4, 
742                                             GEDCOM_MAKE_STRING($4));
743                    START(CHAR, $<ctxt>$)
744                  }
745                  head_char_subs
746                  { CHECK0 }
747                  CLOSE
748                  { end_element(ELT_HEAD_CHAR, PARENT, $<ctxt>5, NULL);
749                  }
750                ;
751
752 head_char_subs : /* empty */
753                | head_char_subs head_char_sub
754                ;
755
756 head_char_sub  : head_char_vers_sect  { OCCUR2(VERS, 0, 1) }
757                | no_std_sub
758                ;
759 head_char_vers_sect : OPEN DELIM TAG_VERS mand_line_item   
760                       { $<ctxt>$ = start_element(ELT_HEAD_CHAR_VERS,
761                                                  PARENT, $1, $3, $4, 
762                                                  GEDCOM_MAKE_STRING($4));
763                         START(VERS, $<ctxt>$)
764                       }
765                       no_std_subs
766                       { CHECK0 }
767                       CLOSE
768                       { end_element(ELT_HEAD_CHAR_VERS,
769                                     PARENT, $<ctxt>5, NULL);
770                       }
771                     ;
772
773 /* HEAD.LANG */
774 head_lang_sect : OPEN DELIM TAG_LANG mand_line_item   
775                  { $<ctxt>$ = start_element(ELT_HEAD_LANG,
776                                             PARENT, $1, $3, $4, 
777                                             GEDCOM_MAKE_STRING($4));
778                    START(LANG, $<ctxt>$)
779                  }
780                  no_std_subs
781                  { CHECK0 }
782                  CLOSE
783                  { end_element(ELT_HEAD_LANG, PARENT, $<ctxt>5, NULL);
784                  }
785                ;
786 /* HEAD.PLAC */
787 head_plac_sect : OPEN DELIM TAG_PLAC
788                  { $<ctxt>$ = start_element(ELT_HEAD_PLAC,
789                                             PARENT, $1, $3, NULL, NULL);
790                    START(PLAC, $<ctxt>$)
791                  }
792                  head_plac_subs
793                  { CHECK1(FORM) }
794                  CLOSE
795                  { end_element(ELT_HEAD_PLAC, PARENT, $<ctxt>4, NULL);
796                  }
797                ;
798
799 head_plac_subs : /* empty */
800                | head_plac_subs head_plac_sub
801                ;
802
803 head_plac_sub  : head_plac_form_sect  { OCCUR2(FORM, 1, 1) }
804                | no_std_sub
805                ;
806 head_plac_form_sect : OPEN DELIM TAG_FORM mand_line_item   
807                       { $<ctxt>$ = start_element(ELT_HEAD_PLAC_FORM,
808                                                  PARENT, $1, $3, $4, 
809                                                  GEDCOM_MAKE_STRING($4));
810                         START(FORM, $<ctxt>$)
811                       }
812                       no_std_subs
813                       { CHECK0 }
814                       CLOSE
815                       { end_element(ELT_HEAD_PLAC_FORM,
816                                     PARENT, $<ctxt>5, NULL);
817                       }
818                     ;
819
820 /* HEAD.NOTE */
821 head_note_sect : OPEN DELIM TAG_NOTE mand_line_item 
822                  { $<ctxt>$ = start_element(ELT_HEAD_NOTE,
823                                             PARENT, $1, $3, $4, 
824                                             GEDCOM_MAKE_STRING($4));
825                    START(NOTE, $<ctxt>$)
826                  }
827                  head_note_subs
828                  { CHECK0 }
829                  CLOSE
830                  { end_element(ELT_HEAD_NOTE, PARENT, $<ctxt>5, NULL);
831                  }
832                ;
833
834 head_note_subs : /* empty */
835                | head_note_subs head_note_sub
836                ;
837
838 head_note_sub  : continuation_sub  /* 0:M */
839                | no_std_sub
840                ;
841
842 /*********************************************************************/
843 /**** Trailer                                                     ****/
844 /*********************************************************************/
845 /* Don't need callbacks here, there is no information... */
846 trlr_sect   : OPEN DELIM TAG_TRLR CLOSE { }
847             ;
848
849 /*********************************************************************/
850 /**** Family record                                               ****/
851 /*********************************************************************/
852 fam_rec      : OPEN DELIM POINTER DELIM TAG_FAM
853                { $<ctxt>$ = start_record(REC_FAM, $1, $3, $5);
854                  START(FAM, $<ctxt>$) }
855                fam_subs
856                { CHECK0 }
857                CLOSE
858                { end_record(REC_FAM, $<ctxt>6); }
859              ;
860
861 fam_subs     : /* empty */
862              | fam_subs fam_sub
863              ;
864
865 fam_sub      : fam_event_struc_sub  /* 0:M */
866              | fam_husb_sect  { OCCUR2(HUSB, 0, 1) }
867              | fam_wife_sect  { OCCUR2(WIFE, 0, 1) }
868              | fam_chil_sect  /* 0:M */
869              | fam_nchi_sect  { OCCUR2(NCHI, 0, 1) }
870              | fam_subm_sect  /* 0:M */
871              | lds_spouse_seal_sub  /* 0:M */
872              | source_cit_sub  /* 0:M */
873              | multim_link_sub  /* 0:M */
874              | note_struc_sub  /* 0:M */
875              | ident_struc_sub  /* 0:1 */
876              | change_date_sub  /* 0:1 */
877              | no_std_sub
878              ;
879
880 /* FAM.HUSB */
881 fam_husb_sect : OPEN DELIM TAG_HUSB mand_pointer    
882                 { $<ctxt>$ = start_element(ELT_FAM_HUSB,
883                                            PARENT, $1, $3, $4, 
884                                            GEDCOM_MAKE_STRING($4));
885                   START(HUSB, $<ctxt>$)
886                 }
887                 no_std_subs
888                 { CHECK0 }
889                 CLOSE
890                 { end_element(ELT_FAM_HUSB, PARENT, $<ctxt>5, NULL);
891                 }
892               ;
893
894 /* FAM.WIFE */
895 fam_wife_sect : OPEN DELIM TAG_WIFE mand_pointer 
896                 { $<ctxt>$ = start_element(ELT_FAM_WIFE,
897                                            PARENT, $1, $3, $4, 
898                                            GEDCOM_MAKE_STRING($4));
899                   START(WIFE, $<ctxt>$)
900                 }
901                 no_std_subs
902                 { CHECK0 }
903                 CLOSE
904                 { end_element(ELT_FAM_WIFE, PARENT, $<ctxt>5, NULL);
905                 }
906               ;
907
908 /* FAM.CHIL */
909 fam_chil_sect : OPEN DELIM TAG_CHIL mand_pointer
910                 { $<ctxt>$ = start_element(ELT_FAM_CHIL,
911                                            PARENT, $1, $3, $4, 
912                                            GEDCOM_MAKE_STRING($4));
913                   START(CHIL, $<ctxt>$) 
914                 } 
915                 no_std_subs 
916                 { CHECK0 } 
917                 CLOSE
918                 { end_element(ELT_FAM_CHIL, PARENT, $<ctxt>5, NULL);
919                 }
920               ;
921
922 /* FAM.NCHI */
923 fam_nchi_sect : OPEN DELIM TAG_NCHI mand_line_item    
924                 { $<ctxt>$ = start_element(ELT_FAM_NCHI,
925                                            PARENT, $1, $3, $4, 
926                                            GEDCOM_MAKE_STRING($4));
927                   START(NCHI, $<ctxt>$)  
928                 }  
929                 no_std_subs  
930                 { CHECK0 }  
931                 CLOSE
932                 { end_element(ELT_FAM_NCHI, PARENT, $<ctxt>5, NULL);
933                 }
934               ;
935
936 /* FAM.SUBM */
937 fam_subm_sect : OPEN DELIM TAG_SUBM mand_pointer
938                 { $<ctxt>$ = start_element(ELT_FAM_SUBM,
939                                            PARENT, $1, $3, $4, 
940                                            GEDCOM_MAKE_STRING($4));
941                   START(SUBM, $<ctxt>$)   
942                 }   
943                 no_std_subs   
944                 { CHECK0 }   
945                 CLOSE
946                 { end_element(ELT_FAM_SUBM, PARENT, $<ctxt>5, NULL);
947                 }
948               ;
949
950 /*********************************************************************/
951 /**** Individual record                                           ****/
952 /*********************************************************************/
953 indiv_rec   : OPEN DELIM POINTER DELIM TAG_INDI
954               { $<ctxt>$ = start_record(REC_INDI, $1, $3, $5);
955                 START(INDI, $<ctxt>$) }
956               indi_subs
957               { CHECK0 }
958               CLOSE
959               { end_record(REC_INDI, $<ctxt>6); }
960             ;
961
962 indi_subs   : /* empty */
963             | indi_subs indi_sub
964             ;
965
966 indi_sub    : indi_resn_sect  { OCCUR2(RESN, 0, 1) }
967             | pers_name_struc_sub  /* 0:M */
968             | indi_sex_sect  { OCCUR2(SEX, 0, 1) }
969             | indiv_even_struc_sub  /* 0:M */
970             | indiv_attr_struc_sub  /* 0:M */
971             | lds_indiv_ord_sub  /* 0:M */
972             | chi_fam_link_sub  /* 0:M */
973             | spou_fam_link_sub  /* 0:M */
974             | indi_subm_sect  /* 0:M */
975             | assoc_struc_sub  /* 0:M */
976             | indi_alia_sect  /* 0:M */
977             | indi_anci_sect  /* 0:M */
978             | indi_desi_sect  /* 0:M */
979             | source_cit_sub  /* 0:M */
980             | multim_link_sub  /* 0:M */
981             | note_struc_sub  /* 0:M */
982             | indi_rfn_sect  { OCCUR2(RFN, 0, 1) }
983             | indi_afn_sect  /* 0:M */
984             | ident_struc_sub  /* 0:1 */
985             | change_date_sub  /* 0:1 */
986             | ftree_addr_sect { if (!compat_mode(C_FTREE))
987                                   INVALID_TAG("ADDR");
988                               }
989             | no_std_sub
990             ;
991
992 /* INDI.RESN */
993 indi_resn_sect : OPEN DELIM TAG_RESN mand_line_item     
994                  { $<ctxt>$ = start_element(ELT_INDI_RESN,
995                                             PARENT, $1, $3, $4, 
996                                             GEDCOM_MAKE_STRING($4));
997                    START(RESN, $<ctxt>$)    
998                  }    
999                  no_std_subs     
1000                  { CHECK0 }     
1001                  CLOSE     
1002                  { end_element(ELT_INDI_RESN, PARENT, $<ctxt>5, NULL);
1003                  }
1004                ;
1005
1006 /* INDI.SEX */
1007 indi_sex_sect  : OPEN DELIM TAG_SEX mand_line_item     
1008                  { $<ctxt>$ = start_element(ELT_INDI_SEX,
1009                                             PARENT, $1, $3, $4, 
1010                                             GEDCOM_MAKE_STRING($4));
1011                    START(SEX, $<ctxt>$)     
1012                  }     
1013                  no_std_subs     
1014                  { CHECK0 }     
1015                  CLOSE     
1016                  { end_element(ELT_INDI_SEX, PARENT, $<ctxt>5, NULL);
1017                  }
1018                ;
1019
1020 /* INDI.SUBM */
1021 indi_subm_sect : OPEN DELIM TAG_SUBM mand_pointer 
1022                  { $<ctxt>$ = start_element(ELT_INDI_SUBM,
1023                                             PARENT, $1, $3, $4, 
1024                                             GEDCOM_MAKE_STRING($4));
1025                    START(SUBM, $<ctxt>$)      
1026                  }      
1027                  no_std_subs      
1028                  { CHECK0 }      
1029                  CLOSE      
1030                  { end_element(ELT_INDI_SUBM, PARENT, $<ctxt>5, NULL);
1031                  }
1032                ;
1033
1034 /* INDI.ALIA */
1035 indi_alia_sect : OPEN DELIM TAG_ALIA mand_pointer
1036                  { $<ctxt>$ = start_element(ELT_INDI_ALIA,
1037                                             PARENT, $1, $3, $4, 
1038                                             GEDCOM_MAKE_STRING($4));
1039                    START(ALIA, $<ctxt>$)       
1040                  }       
1041                  no_std_subs       
1042                  { CHECK0 }       
1043                  CLOSE       
1044                  { end_element(ELT_INDI_ALIA, PARENT, $<ctxt>5, NULL);
1045                  }
1046                ;
1047
1048 /* INDI.ANCI */
1049 indi_anci_sect : OPEN DELIM TAG_ANCI mand_pointer
1050                  { $<ctxt>$ = start_element(ELT_INDI_ANCI,
1051                                             PARENT, $1, $3, $4, 
1052                                             GEDCOM_MAKE_STRING($4));
1053                    START(ANCI, $<ctxt>$)        
1054                  }        
1055                  no_std_subs        
1056                  { CHECK0 }        
1057                  CLOSE        
1058                  { end_element(ELT_INDI_ANCI, PARENT, $<ctxt>5, NULL);
1059                  }
1060                ;
1061
1062 /* INDI.DESI */
1063 indi_desi_sect : OPEN DELIM TAG_DESI mand_pointer
1064                  { $<ctxt>$ = start_element(ELT_INDI_DESI,
1065                                             PARENT, $1, $3, $4, 
1066                                             GEDCOM_MAKE_STRING($4));
1067                    START(DESI, $<ctxt>$)         
1068                  }         
1069                  no_std_subs         
1070                  { CHECK0 }         
1071                  CLOSE         
1072                  { end_element(ELT_INDI_DESI, PARENT, $<ctxt>5, NULL);
1073                  }
1074                ;
1075
1076 /* INDI.RFN */
1077 indi_rfn_sect  : OPEN DELIM TAG_RFN mand_line_item     
1078                  { $<ctxt>$ = start_element(ELT_INDI_RFN,
1079                                             PARENT, $1, $3, $4, 
1080                                             GEDCOM_MAKE_STRING($4));
1081                    START(RFN, $<ctxt>$)          
1082                  }          
1083                  no_std_subs          
1084                  { CHECK0 }          
1085                  CLOSE          
1086                  { end_element(ELT_INDI_RFN, PARENT, $<ctxt>5, NULL);
1087                  }
1088                ;
1089
1090 /* INDI.AFN */
1091 indi_afn_sect  : OPEN DELIM TAG_AFN mand_line_item      
1092                  { $<ctxt>$ = start_element(ELT_INDI_AFN,
1093                                             PARENT, $1, $3, $4, 
1094                                             GEDCOM_MAKE_STRING($4));
1095                    START(AFN, $<ctxt>$)           
1096                  }           
1097                  no_std_subs           
1098                  { CHECK0 }           
1099                  CLOSE           
1100                  { end_element(ELT_INDI_AFN, PARENT, $<ctxt>5, NULL);
1101                  }
1102                ;
1103
1104 /* INDI.ADDR (Only for 'ftree' compatibility) */
1105 ftree_addr_sect : OPEN DELIM TAG_ADDR opt_line_item
1106                   { START(ADDR, NULL) } no_std_subs { CHECK0 } CLOSE { }
1107
1108 /*********************************************************************/
1109 /**** Multimedia record                                           ****/
1110 /*********************************************************************/
1111 multim_rec  : OPEN DELIM POINTER DELIM TAG_OBJE
1112               { $<ctxt>$ = start_record(REC_OBJE, $1, $3, $5);
1113                 START(OBJE, $<ctxt>$) }
1114               obje_subs
1115               { CHECK2(FORM, BLOB) }
1116               CLOSE
1117               { end_record(REC_OBJE, $<ctxt>6); }
1118             ;
1119
1120 obje_subs   : /* empty */
1121             | obje_subs obje_sub
1122             ;
1123
1124 obje_sub    : obje_form_sect  { OCCUR2(FORM, 1, 1) }
1125             | obje_titl_sect  { OCCUR2(TITL, 0, 1) }
1126             | note_struc_sub  /* 0:M */
1127             | obje_blob_sect  { OCCUR2(BLOB, 1, 1) }
1128             | obje_obje_sect  { OCCUR2(OBJE, 0, 1) }
1129             | ident_struc_sub  /* 0:1 */
1130             | change_date_sub  /* 0:1 */
1131             | no_std_sub
1132             ;
1133
1134 /* OBJE.FORM */
1135 obje_form_sect : OPEN DELIM TAG_FORM mand_line_item       
1136                  { $<ctxt>$ = start_element(ELT_OBJE_FORM,
1137                                             PARENT, $1, $3, $4, 
1138                                             GEDCOM_MAKE_STRING($4));
1139                    START(FORM, $<ctxt>$)            
1140                  }            
1141                  no_std_subs            
1142                  { CHECK0 }            
1143                  CLOSE            
1144                  { end_element(ELT_OBJE_FORM, PARENT, $<ctxt>5, NULL);
1145                  }
1146                ;
1147
1148 /* OBJE.TITL */
1149 obje_titl_sect : OPEN DELIM TAG_TITL mand_line_item       
1150                  { $<ctxt>$ = start_element(ELT_OBJE_TITL,
1151                                             PARENT, $1, $3, $4, 
1152                                             GEDCOM_MAKE_STRING($4));
1153                    START(TITL, $<ctxt>$)             
1154                  }             
1155                  no_std_subs             
1156                  { CHECK0 }             
1157                  CLOSE             
1158                  { end_element(ELT_OBJE_TITL, PARENT, $<ctxt>5, NULL);
1159                  }
1160                ;
1161
1162 /* OBJE.BLOB */
1163 obje_blob_sect : OPEN DELIM TAG_BLOB
1164                  { $<ctxt>$ = start_element(ELT_OBJE_BLOB,
1165                                             PARENT, $1, $3, NULL, NULL);
1166                    START(BLOB, $<ctxt>$)              
1167                  }
1168                  obje_blob_subs
1169                  { CHECK1(CONT) }
1170                  CLOSE              
1171                  { end_element(ELT_OBJE_BLOB, PARENT, $<ctxt>4, NULL);
1172                  }
1173                ;
1174
1175 obje_blob_subs : /* empty */
1176                | obje_blob_subs obje_blob_sub
1177                ;
1178
1179 obje_blob_sub  : obje_blob_cont_sect  { OCCUR1(CONT, 1) }
1180                | no_std_sub
1181                ;
1182
1183 obje_blob_cont_sect : OPEN DELIM TAG_CONT mand_line_item        
1184                       { $<ctxt>$ = start_element(ELT_OBJE_BLOB_CONT,
1185                                                  PARENT, $1, $3, $4, 
1186                                                  GEDCOM_MAKE_STRING($4));
1187                         START(CONT, $<ctxt>$)               
1188                       }                
1189                       no_std_subs                
1190                       { CHECK0 }                
1191                       CLOSE                
1192                       { end_element(ELT_OBJE_BLOB_CONT, PARENT,
1193                                     $<ctxt>5, NULL);
1194                       }
1195                     ;
1196
1197 /* OBJE.OBJE */
1198 obje_obje_sect : OPEN DELIM TAG_OBJE mand_pointer 
1199                  { $<ctxt>$ = start_element(ELT_OBJE_OBJE,
1200                                             PARENT, $1, $3, $4, 
1201                                             GEDCOM_MAKE_STRING($4));
1202                    START(OBJE, $<ctxt>$)  
1203                  }  
1204                  no_std_subs  
1205                  { CHECK0 }  
1206                  CLOSE  
1207                  { end_element(ELT_OBJE_OBJE, PARENT, $<ctxt>5, NULL);
1208                  }
1209                ;
1210
1211 /*********************************************************************/
1212 /**** Note record                                                 ****/
1213 /*********************************************************************/
1214 note_rec    : OPEN DELIM POINTER DELIM TAG_NOTE note_line_item
1215               { $<ctxt>$ = start_record(REC_NOTE, $1, $3, $5);
1216                 START(NOTE, $<ctxt>$) }
1217               note_subs
1218               { CHECK0 }
1219               CLOSE
1220               { end_record(REC_NOTE, $<ctxt>6); }
1221             ;
1222
1223 note_line_item : /* empty */
1224                    { if (!compat_mode(C_FTREE)) {
1225                        gedcom_error(_("Missing value")); YYERROR;
1226                      }
1227                    }
1228                | DELIM line_item
1229                    { gedcom_debug_print("==Val: %s==", $2);
1230                      $$ = $2; }
1231                ;
1232
1233 note_subs   : /* empty */
1234             | note_subs note_sub
1235             ;
1236
1237 note_sub    : continuation_sub  /* 0:M */
1238             | source_cit_sub  /* 0:M */
1239             | ident_struc_sub  /* 0:1 */
1240             | change_date_sub  /* 0:1 */
1241             | no_std_sub
1242             ;
1243
1244 /*********************************************************************/
1245 /**** Repository record                                           ****/
1246 /*********************************************************************/
1247 repos_rec   : OPEN DELIM POINTER DELIM TAG_REPO
1248               { $<ctxt>$ = start_record(REC_REPO, $1, $3, $5);
1249                 START(REPO, $<ctxt>$) }
1250               repo_subs
1251               { CHECK0 }
1252               CLOSE
1253               { end_record(REC_REPO, $<ctxt>6); }
1254             ;
1255
1256 repo_subs   : /* empty */
1257             | repo_subs repo_sub
1258             ;
1259
1260 repo_sub    : repo_name_sect  { OCCUR2(NAME, 0, 1) }
1261             | addr_struc_sub  /* 0:1 */
1262             | note_struc_sub  /* 0:M */
1263             | ident_struc_sub  /* 0:1 */
1264             | change_date_sub  /* 0:1 */
1265             | no_std_sub
1266             ;
1267
1268 /* REPO.NAME */
1269 repo_name_sect : OPEN DELIM TAG_NAME mand_line_item         
1270                  { $<ctxt>$ = start_element(ELT_REPO_NAME,
1271                                             PARENT, $1, $3, $4, 
1272                                             GEDCOM_MAKE_STRING($4));
1273                    START(NAME, $<ctxt>$)          
1274                  }          
1275                  no_std_subs          
1276                  { CHECK0 }          
1277                  CLOSE          
1278                  { end_element(ELT_REPO_NAME, PARENT, $<ctxt>5, NULL);
1279                  }
1280                ;
1281
1282 /*********************************************************************/
1283 /**** Source record                                               ****/
1284 /*********************************************************************/
1285 source_rec  : OPEN DELIM POINTER DELIM TAG_SOUR
1286               { $<ctxt>$ = start_record(REC_SOUR, $1, $3, $5);
1287                 START(SOUR, $<ctxt>$) }
1288               sour_subs
1289               { CHECK0 }
1290               CLOSE
1291               { end_record(REC_SOUR, $<ctxt>6); }
1292             ;
1293
1294 sour_subs   : /* empty */
1295             | sour_subs sour_sub
1296             ;
1297
1298 sour_sub    : sour_data_sect  { OCCUR2(DATA, 0, 1) }
1299             | sour_auth_sect  { OCCUR2(AUTH, 0, 1) }
1300             | sour_titl_sect  { OCCUR2(TITL, 0, 1) }
1301             | sour_abbr_sect  { OCCUR2(ABBR, 0, 1) }
1302             | sour_publ_sect  { OCCUR2(PUBL, 0, 1) }
1303             | sour_text_sect  { OCCUR2(TEXT, 0, 1) }
1304             | source_repos_cit_sub  /* 0:1 */
1305             | multim_link_sub  /* 0:M */
1306             | note_struc_sub  /* 0:M */
1307             | ident_struc_sub  /* 0:1 */
1308             | change_date_sub  /* 0:1 */
1309             | no_std_sub
1310             ;
1311
1312 /* SOUR.DATA */
1313 sour_data_sect : OPEN DELIM TAG_DATA
1314                  { $<ctxt>$ = start_element(ELT_SOUR_DATA,
1315                                             PARENT, $1, $3, NULL, NULL);
1316                    START(DATA, $<ctxt>$) 
1317                  }
1318                  sour_data_subs
1319                  { CHECK0 }
1320                  CLOSE 
1321                  { end_element(ELT_SOUR_DATA, PARENT, $<ctxt>4, NULL);
1322                  }
1323                ;
1324
1325 sour_data_subs : /* empty */
1326                | sour_data_subs sour_data_sub
1327                ;
1328
1329 sour_data_sub  : sour_data_even_sect  /* 0:M */
1330                | sour_data_agnc_sect  { OCCUR2(AGNC, 0, 1) }
1331                | note_struc_sub  /* 0:M */
1332                | no_std_sub
1333                ;
1334
1335 sour_data_even_sect : OPEN DELIM TAG_EVEN mand_line_item 
1336                       { $<ctxt>$ = start_element(ELT_SOUR_DATA_EVEN,
1337                                                  PARENT, $1, $3, $4, 
1338                                                  GEDCOM_MAKE_STRING($4));
1339                         START(EVEN, $<ctxt>$)  
1340                       }
1341                       sour_data_even_subs
1342                       { CHECK0 }
1343                       CLOSE  
1344                       { end_element(ELT_SOUR_DATA_EVEN, PARENT,
1345                                     $<ctxt>5, NULL);
1346                       }
1347                     ;
1348
1349 sour_data_even_subs : /* empty */
1350                     | sour_data_even_subs sour_data_even_sub
1351                     ;
1352
1353 sour_data_even_sub  : sour_data_even_date_sect { OCCUR2(DATE, 0, 1) }
1354                     | sour_data_even_plac_sect { OCCUR2(PLAC, 0, 1) }
1355                     | no_std_sub
1356                     ;
1357
1358 sour_data_even_date_sect : OPEN DELIM TAG_DATE mand_line_item          
1359                            { struct date_value dv = gedcom_parse_date($4);
1360                              $<ctxt>$ = start_element(ELT_SOUR_DATA_EVEN_DATE,
1361                                                       PARENT, $1, $3, $4, 
1362                                                       GEDCOM_MAKE_DATE(dv));
1363                              START(DATE, $<ctxt>$)           
1364                            }           
1365                            no_std_subs           
1366                            { CHECK0 }           
1367                            CLOSE           
1368                            { end_element(ELT_SOUR_DATA_EVEN_DATE, PARENT,
1369                                          $<ctxt>5, NULL);
1370                            }
1371                          ;
1372
1373 sour_data_even_plac_sect : OPEN DELIM TAG_PLAC mand_line_item          
1374                            { $<ctxt>$ = start_element(ELT_SOUR_DATA_EVEN_PLAC,
1375                                                       PARENT, $1, $3, $4, 
1376                                                       GEDCOM_MAKE_STRING($4));
1377                              START(PLAC, $<ctxt>$)           
1378                            }           
1379                            no_std_subs           
1380                            { CHECK0 }           
1381                            CLOSE           
1382                            { end_element(ELT_SOUR_DATA_EVEN_PLAC, PARENT,
1383                                          $<ctxt>5, NULL);
1384                            }
1385                          ;
1386
1387 sour_data_agnc_sect : OPEN DELIM TAG_AGNC mand_line_item          
1388                       { $<ctxt>$ = start_element(ELT_SOUR_DATA_AGNC,
1389                                                  PARENT, $1, $3, $4, 
1390                                                  GEDCOM_MAKE_STRING($4));
1391                         START(AGNC, $<ctxt>$)           
1392                       }           
1393                       no_std_subs           
1394                       { CHECK0 }           
1395                       CLOSE           
1396                       { end_element(ELT_SOUR_DATA_AGNC, PARENT,
1397                                     $<ctxt>5, NULL);
1398                       }
1399                     ;
1400
1401 /* SOUR.AUTH */
1402 sour_auth_sect : OPEN DELIM TAG_AUTH mand_line_item
1403                  { $<ctxt>$ = start_element(ELT_SOUR_AUTH,
1404                                             PARENT, $1, $3, $4, 
1405                                             GEDCOM_MAKE_STRING($4));
1406                    START(AUTH, $<ctxt>$) 
1407                  }
1408                  sour_auth_subs
1409                  { CHECK0 }
1410                  CLOSE 
1411                  { end_element(ELT_SOUR_AUTH, PARENT, $<ctxt>5, NULL);
1412                  }
1413                ;
1414
1415 sour_auth_subs : /* empty */
1416                | sour_auth_subs sour_auth_sub
1417                ;
1418
1419 sour_auth_sub  : continuation_sub  /* 0:M */
1420                | no_std_sub
1421                ;
1422
1423 /* SOUR.TITL */
1424 sour_titl_sect : OPEN DELIM TAG_TITL mand_line_item  
1425                  { $<ctxt>$ = start_element(ELT_SOUR_TITL,
1426                                             PARENT, $1, $3, $4, 
1427                                             GEDCOM_MAKE_STRING($4));
1428                    START(TITL, $<ctxt>$)   
1429                  }
1430                  sour_titl_subs 
1431                  { CHECK0 }
1432                  CLOSE   
1433                  { end_element(ELT_SOUR_TITL, PARENT, $<ctxt>5, NULL);
1434                  }
1435                ;
1436
1437 sour_titl_subs : /* empty */
1438                | sour_titl_subs sour_titl_sub
1439                ;
1440
1441 sour_titl_sub  : continuation_sub  /* 0:M */
1442                | no_std_sub
1443                ;
1444
1445 /* SOUR.ABBR */
1446 sour_abbr_sect : OPEN DELIM TAG_ABBR mand_line_item           
1447                  { $<ctxt>$ = start_element(ELT_SOUR_ABBR,
1448                                             PARENT, $1, $3, $4, 
1449                                             GEDCOM_MAKE_STRING($4));
1450                    START(ABBR, $<ctxt>$)            
1451                  }            
1452                  no_std_subs            
1453                  { CHECK0 }            
1454                  CLOSE            
1455                  { end_element(ELT_SOUR_ABBR, PARENT, $<ctxt>5, NULL);
1456                  }
1457                ;
1458
1459 /* SOUR.PUBL */
1460 sour_publ_sect : OPEN DELIM TAG_PUBL mand_line_item  
1461                  { $<ctxt>$ = start_element(ELT_SOUR_PUBL,
1462                                             PARENT, $1, $3, $4, 
1463                                             GEDCOM_MAKE_STRING($4));
1464                    START(PUBL, $<ctxt>$)            
1465                  }
1466                  sour_publ_subs  
1467                  { CHECK0 }
1468                  CLOSE            
1469                  { end_element(ELT_SOUR_PUBL, PARENT, $<ctxt>5, NULL);
1470                  }
1471                ;
1472
1473 sour_publ_subs : /* empty */
1474                | sour_publ_subs sour_publ_sub
1475                ;
1476
1477 sour_publ_sub  : continuation_sub  /* 0:M */
1478                | no_std_sub
1479                ;
1480
1481 /* SOUR.TEXT */
1482 sour_text_sect : OPEN DELIM TAG_TEXT mand_line_item   
1483                  { $<ctxt>$ = start_element(ELT_SOUR_TEXT,
1484                                             PARENT, $1, $3, $4, 
1485                                             GEDCOM_MAKE_STRING($4));
1486                    START(TEXT, $<ctxt>$)    
1487                  }
1488                  sour_text_subs  
1489                  { CHECK0 }
1490                  CLOSE    
1491                  { end_element(ELT_SOUR_TEXT, PARENT, $<ctxt>5, NULL);
1492                  }
1493                ;
1494
1495 sour_text_subs : /* empty */
1496                | sour_text_subs sour_text_sub
1497                ;
1498
1499 sour_text_sub  : continuation_sub  /* 0:M */
1500                | no_std_sub
1501                ;
1502
1503 /*********************************************************************/
1504 /**** Submission record                                           ****/
1505 /*********************************************************************/
1506 submis_rec  : OPEN DELIM POINTER DELIM TAG_SUBN    
1507               { $<ctxt>$ = start_record(REC_SUBN, $1, $3, $5);
1508                 START(SUBN, $<ctxt>$) }
1509               subn_subs
1510               { CHECK0 }
1511               CLOSE
1512               { end_record(REC_SUBN, $<ctxt>6); }
1513             ;
1514
1515 subn_subs   : /* empty */
1516             | subn_subs subn_sub
1517             ;
1518
1519 subn_sub    : subn_subm_sect  { OCCUR2(SUBM, 0, 1) }
1520             | subn_famf_sect  { OCCUR2(FAMF, 0, 1) }
1521             | subn_temp_sect  { OCCUR2(TEMP, 0, 1) }
1522             | subn_ance_sect  { OCCUR2(ANCE, 0, 1) }
1523             | subn_desc_sect  { OCCUR2(DESC, 0, 1) }
1524             | subn_ordi_sect  { OCCUR2(ORDI, 0, 1) }
1525             | subn_rin_sect  { OCCUR2(RIN, 0, 1) }
1526             | no_std_sub
1527             ;
1528
1529 /* SUBN.SUBM */
1530 subn_subm_sect : OPEN DELIM TAG_SUBM mand_pointer
1531                  { $<ctxt>$ = start_element(ELT_SUBN_SUBM,
1532                                             PARENT, $1, $3, $4, 
1533                                             GEDCOM_MAKE_STRING($4));
1534                    START(SUBM, $<ctxt>$) 
1535                  } 
1536                  no_std_subs 
1537                  { CHECK0 } 
1538                  CLOSE 
1539                  { end_element(ELT_SUBN_SUBM, PARENT, $<ctxt>5, NULL);
1540                  }
1541                ;
1542
1543 /* SUBN.FAMF */
1544 subn_famf_sect : OPEN DELIM TAG_FAMF mand_line_item            
1545                  { $<ctxt>$ = start_element(ELT_SUBN_FAMF,
1546                                             PARENT, $1, $3, $4, 
1547                                             GEDCOM_MAKE_STRING($4));
1548                    START(FAMF, $<ctxt>$)             
1549                  }             
1550                  no_std_subs             
1551                  { CHECK0 }             
1552                  CLOSE             
1553                  { end_element(ELT_SUBN_FAMF, PARENT, $<ctxt>5, NULL);
1554                  }
1555                ;
1556
1557 /* SUBN.TEMP */
1558 subn_temp_sect : OPEN DELIM TAG_TEMP mand_line_item            
1559                  { $<ctxt>$ = start_element(ELT_SUBN_TEMP,
1560                                             PARENT, $1, $3, $4, 
1561                                             GEDCOM_MAKE_STRING($4));
1562                    START(TEMP, $<ctxt>$)             
1563                  }             
1564                  no_std_subs             
1565                  { CHECK0 }             
1566                  CLOSE             
1567                  { end_element(ELT_SUBN_TEMP, PARENT, $<ctxt>5, NULL);
1568                  }
1569                ;
1570
1571 /* SUBN.ANCE */
1572 subn_ance_sect : OPEN DELIM TAG_ANCE mand_line_item            
1573                  { $<ctxt>$ = start_element(ELT_SUBN_ANCE,
1574                                             PARENT, $1, $3, $4, 
1575                                             GEDCOM_MAKE_STRING($4));
1576                    START(ANCE, $<ctxt>$)             
1577                  }             
1578                  no_std_subs             
1579                  { CHECK0 }             
1580                  CLOSE             
1581                  { end_element(ELT_SUBN_ANCE, PARENT, $<ctxt>5, NULL);
1582                  }
1583                ;
1584
1585 /* SUBN.DESC */
1586 subn_desc_sect : OPEN DELIM TAG_DESC mand_line_item            
1587                  { $<ctxt>$ = start_element(ELT_SUBN_DESC,
1588                                             PARENT, $1, $3, $4, 
1589                                             GEDCOM_MAKE_STRING($4));
1590                    START(DESC, $<ctxt>$)             
1591                  }             
1592                  no_std_subs             
1593                  { CHECK0 }             
1594                  CLOSE             
1595                  { end_element(ELT_SUBN_DESC, PARENT, $<ctxt>5, NULL);
1596                  }
1597                ;
1598
1599 /* SUBN.ORDI */
1600 subn_ordi_sect : OPEN DELIM TAG_ORDI mand_line_item            
1601                  { $<ctxt>$ = start_element(ELT_SUBN_ORDI,
1602                                             PARENT, $1, $3, $4, 
1603                                             GEDCOM_MAKE_STRING($4));
1604                    START(ORDI, $<ctxt>$)             
1605                  }             
1606                  no_std_subs             
1607                  { CHECK0 }             
1608                  CLOSE             
1609                  { end_element(ELT_SUBN_ORDI, PARENT, $<ctxt>5, NULL);
1610                  }
1611                ;
1612
1613 /* SUBN.RIN */
1614 subn_rin_sect  : OPEN DELIM TAG_RIN mand_line_item            
1615                  { $<ctxt>$ = start_element(ELT_SUBN_RIN,
1616                                             PARENT, $1, $3, $4, 
1617                                             GEDCOM_MAKE_STRING($4));
1618                    START(RIN, $<ctxt>$)             
1619                  }             
1620                  no_std_subs             
1621                  { CHECK0 }             
1622                  CLOSE             
1623                  { end_element(ELT_SUBN_RIN, PARENT, $<ctxt>5, NULL);
1624                  }
1625                ;
1626
1627 /*********************************************************************/
1628 /**** Submitter record                                            ****/
1629 /*********************************************************************/
1630 submit_rec : OPEN DELIM POINTER DELIM TAG_SUBM    
1631              { $<ctxt>$ = start_record(REC_SUBM, $1, $3, $5);
1632                 START(SUBM, $<ctxt>$) }
1633              subm_subs
1634              { CHECK1(NAME) }
1635              CLOSE
1636              { end_record(REC_SUBM, $<ctxt>6); }
1637            ;
1638
1639 subm_subs  : /* empty */
1640            | subm_subs subm_sub
1641            ;
1642
1643 subm_sub   : subm_name_sect  { OCCUR2(NAME, 0, 1) }
1644            | addr_struc_sub  /* 0:1 */
1645            | multim_link_sub  /* 0:M */
1646            | subm_lang_sect  { OCCUR2(LANG, 0, 3) }
1647            | subm_rfn_sect  { OCCUR2(RFN, 0, 1) }
1648            | subm_rin_sect  { OCCUR2(RIN, 0, 1) }
1649            | change_date_sub  /* 0:1 */
1650            | no_std_sub
1651            ;
1652
1653 /* SUBM.NAME */
1654 subm_name_sect : OPEN DELIM TAG_NAME mand_line_item             
1655                  { $<ctxt>$ = start_element(ELT_SUBM_NAME,
1656                                             PARENT, $1, $3, $4, 
1657                                             GEDCOM_MAKE_STRING($4));
1658                    START(NAME, $<ctxt>$)              
1659                  }              
1660                  no_std_subs              
1661                  { CHECK0 }              
1662                  CLOSE              
1663                  { end_element(ELT_SUBM_NAME, PARENT, $<ctxt>5, NULL);
1664                  }
1665                ;
1666
1667 /* SUBM.LANG */
1668 subm_lang_sect : OPEN DELIM TAG_LANG mand_line_item             
1669                  { $<ctxt>$ = start_element(ELT_SUBM_LANG,
1670                                             PARENT, $1, $3, $4, 
1671                                             GEDCOM_MAKE_STRING($4));
1672                    START(LANG, $<ctxt>$)              
1673                  }              
1674                  no_std_subs              
1675                  { CHECK0 }              
1676                  CLOSE              
1677                  { end_element(ELT_SUBM_LANG, PARENT, $<ctxt>5, NULL);
1678                  }
1679                ;
1680
1681 /* SUBM.RFN */
1682 subm_rfn_sect  : OPEN DELIM TAG_RFN mand_line_item             
1683                  { $<ctxt>$ = start_element(ELT_SUBM_RFN,
1684                                             PARENT, $1, $3, $4, 
1685                                             GEDCOM_MAKE_STRING($4));
1686                    START(RFN, $<ctxt>$)              
1687                  }              
1688                  no_std_subs              
1689                  { CHECK0 }              
1690                  CLOSE              
1691                  { end_element(ELT_SUBM_RFN, PARENT, $<ctxt>5, NULL);
1692                  }
1693                ;
1694
1695 /* SUBM.RIN */
1696 subm_rin_sect  : OPEN DELIM TAG_RIN mand_line_item             
1697                  { $<ctxt>$ = start_element(ELT_SUBM_RIN,
1698                                             PARENT, $1, $3, $4, 
1699                                             GEDCOM_MAKE_STRING($4));
1700                    START(RIN, $<ctxt>$)              
1701                  }              
1702                  no_std_subs              
1703                  { CHECK0 }              
1704                  CLOSE              
1705                  { end_element(ELT_SUBM_RIN, PARENT, $<ctxt>5, NULL);
1706                  }
1707                ;
1708
1709 /*********************************************************************/
1710 /**** Substructures                                               ****/
1711 /*********************************************************************/
1712
1713 /* ADDRESS STRUCTURE */
1714 addr_struc_sub : addr_sect { OCCUR2(ADDR, 0, 1) }
1715                | phon_sect { OCCUR2(PHON, 0, 3) }
1716                ;
1717
1718 addr_sect   : OPEN DELIM TAG_ADDR mand_line_item 
1719               { $<ctxt>$ = start_element(ELT_SUB_ADDR,
1720                                          PARENT, $1, $3, $4, 
1721                                          GEDCOM_MAKE_STRING($4));
1722                 START(ADDR, $<ctxt>$)  
1723               }
1724               addr_subs
1725               { CHECK0 }
1726               CLOSE  
1727               { end_element(ELT_SUB_ADDR, PARENT, $<ctxt>5, NULL);
1728               }
1729             ;
1730
1731 addr_subs   : /* empty */
1732             | addr_subs addr_sub
1733             ;
1734
1735 addr_sub    : addr_cont_sect  /* 0:M */
1736             | addr_adr1_sect  { OCCUR2(ADR1, 0, 1) }
1737             | addr_adr2_sect  { OCCUR2(ADR2, 0, 1) }
1738             | addr_city_sect  { OCCUR2(CITY, 0, 1) }
1739             | addr_stae_sect  { OCCUR2(STAE, 0, 1) }
1740             | addr_post_sect  { OCCUR2(POST, 0, 1) }
1741             | addr_ctry_sect  { OCCUR2(CTRY, 0, 1) }
1742             | no_std_sub
1743             ;
1744
1745 addr_cont_sect : OPEN DELIM TAG_CONT mand_line_item              
1746                  { $<ctxt>$ = start_element(ELT_SUB_ADDR_CONT,
1747                                             PARENT, $1, $3, $4, 
1748                                             GEDCOM_MAKE_STRING($4));
1749                    START(CONT, $<ctxt>$)               
1750                  }               
1751                  no_std_subs               
1752                  { CHECK0 }               
1753                  CLOSE               
1754                  { end_element(ELT_SUB_ADDR_CONT, PARENT, $<ctxt>5, NULL);
1755                  }
1756                ;
1757 addr_adr1_sect : OPEN DELIM TAG_ADR1 mand_line_item              
1758                  { $<ctxt>$ = start_element(ELT_SUB_ADDR_ADR1,
1759                                             PARENT, $1, $3, $4, 
1760                                             GEDCOM_MAKE_STRING($4));
1761                    START(ADR1, $<ctxt>$)               
1762                  }               
1763                  no_std_subs               
1764                  { CHECK0 }               
1765                  CLOSE               
1766                  { end_element(ELT_SUB_ADDR_ADR1, PARENT, $<ctxt>5, NULL);
1767                  }
1768                ;
1769 addr_adr2_sect : OPEN DELIM TAG_ADR2 mand_line_item              
1770                  { $<ctxt>$ = start_element(ELT_SUB_ADDR_ADR2,
1771                                             PARENT, $1, $3, $4, 
1772                                             GEDCOM_MAKE_STRING($4));
1773                    START(ADR2, $<ctxt>$)               
1774                  }               
1775                  no_std_subs               
1776                  { CHECK0 }               
1777                  CLOSE               
1778                  { end_element(ELT_SUB_ADDR_ADR2, PARENT, $<ctxt>5, NULL);
1779                  }
1780                ;
1781 addr_city_sect : OPEN DELIM TAG_CITY mand_line_item              
1782                  { $<ctxt>$ = start_element(ELT_SUB_ADDR_CITY,
1783                                             PARENT, $1, $3, $4, 
1784                                             GEDCOM_MAKE_STRING($4));
1785                    START(CITY, $<ctxt>$)               
1786                  }               
1787                  no_std_subs               
1788                  { CHECK0 }               
1789                  CLOSE               
1790                  { end_element(ELT_SUB_ADDR_CITY, PARENT, $<ctxt>5, NULL);
1791                  }
1792                ;
1793 addr_stae_sect : OPEN DELIM TAG_STAE mand_line_item              
1794                  { $<ctxt>$ = start_element(ELT_SUB_ADDR_STAE,
1795                                             PARENT, $1, $3, $4, 
1796                                             GEDCOM_MAKE_STRING($4));
1797                    START(STAE, $<ctxt>$)               
1798                  }               
1799                  no_std_subs               
1800                  { CHECK0 }               
1801                  CLOSE               
1802                  { end_element(ELT_SUB_ADDR_STAE, PARENT, $<ctxt>5, NULL);
1803                  }
1804                ;
1805 addr_post_sect : OPEN DELIM TAG_POST mand_line_item              
1806                  { $<ctxt>$ = start_element(ELT_SUB_ADDR_POST,
1807                                             PARENT, $1, $3, $4, 
1808                                             GEDCOM_MAKE_STRING($4));
1809                    START(POST, $<ctxt>$)               
1810                  }               
1811                  no_std_subs               
1812                  { CHECK0 }               
1813                  CLOSE               
1814                  { end_element(ELT_SUB_ADDR_POST, PARENT, $<ctxt>5, NULL);
1815                  }
1816                ;
1817 addr_ctry_sect : OPEN DELIM TAG_CTRY mand_line_item              
1818                  { $<ctxt>$ = start_element(ELT_SUB_ADDR_CTRY,
1819                                             PARENT, $1, $3, $4, 
1820                                             GEDCOM_MAKE_STRING($4));
1821                    START(CTRY, $<ctxt>$)               
1822                  }               
1823                  no_std_subs               
1824                  { CHECK0 }               
1825                  CLOSE               
1826                  { end_element(ELT_SUB_ADDR_CTRY, PARENT, $<ctxt>5, NULL);
1827                  }
1828                ;
1829
1830 phon_sect   : OPEN DELIM TAG_PHON mand_line_item              
1831               { $<ctxt>$ = start_element(ELT_SUB_PHON,
1832                                          PARENT, $1, $3, $4, 
1833                                          GEDCOM_MAKE_STRING($4));
1834                 START(PHON, $<ctxt>$)               
1835               }               
1836               no_std_subs               
1837               { CHECK0 }               
1838               CLOSE               
1839               { end_element(ELT_SUB_PHON, PARENT, $<ctxt>5, NULL);
1840               }
1841             ;
1842
1843 /* ASSOCIATION STRUCTURE */
1844 assoc_struc_sub : asso_sect /* 0:M */
1845                 ;
1846
1847 asso_sect : OPEN DELIM TAG_ASSO mand_pointer
1848             { START(ASSO, NULL) }
1849             asso_subs
1850             { CHECK2(TYPE,RELA) }
1851             CLOSE { }
1852           ;
1853
1854 asso_subs : /* empty */
1855           | asso_type_sect  { OCCUR2(TYPE, 1, 1) }
1856           | asso_rela_sect  { OCCUR2(RELA, 1, 1) }
1857           | note_struc_sub
1858           | source_cit_sub
1859           | no_std_sub
1860           ;
1861
1862 asso_type_sect : OPEN DELIM TAG_TYPE mand_line_item               
1863                  { START(TYPE, NULL) } no_std_subs { CHECK0 } CLOSE { }
1864                ;
1865
1866 asso_rela_sect : OPEN DELIM TAG_RELA mand_line_item               
1867                  { START(RELA, NULL) } no_std_subs { CHECK0 } CLOSE { }
1868                ;
1869
1870 /* CHANGE DATE */
1871 change_date_sub : change_date_chan_sect  { OCCUR2(CHAN, 0, 1) }
1872                 ;
1873
1874 change_date_chan_sect : OPEN DELIM TAG_CHAN
1875                         { START(CHAN, NULL) }
1876                         change_date_chan_subs
1877                         { CHECK1(DATE) }
1878                         CLOSE { }
1879                       ;
1880
1881 change_date_chan_subs : /* empty */
1882                       | change_date_chan_subs change_date_chan_sub
1883                       ;
1884
1885 change_date_chan_sub  : change_date_date_sect  { OCCUR2(DATE, 1, 1) }
1886                       | note_struc_sub
1887                       | no_std_sub
1888                       ;
1889
1890 change_date_date_sect : OPEN DELIM TAG_DATE mand_line_item 
1891                         { START(DATE, NULL) }
1892                         change_date_date_subs
1893                         { CHECK0 }
1894                         CLOSE { }
1895                       ;
1896
1897 change_date_date_subs : /* empty */
1898                       | change_date_date_subs change_date_date_sub
1899                       ;
1900
1901 change_date_date_sub : change_date_date_time_sect  { OCCUR2(TIME, 0, 1) }
1902                      | no_std_sub
1903                      ;
1904
1905 change_date_date_time_sect : OPEN DELIM TAG_TIME mand_line_item
1906                              { START(TIME, NULL) } no_std_subs { CHECK0 } CLOSE { }
1907                            ;
1908
1909 /* CHILD TO FAMILY LINK */
1910 chi_fam_link_sub : famc_sect  /* 0:M */
1911                  ;
1912
1913 famc_sect : OPEN DELIM TAG_FAMC mand_pointer
1914             { START(FAMC, NULL) }
1915             famc_subs
1916             { CHECK0 }
1917             CLOSE { }
1918           ;
1919
1920 famc_subs : /* empty */
1921           | famc_subs famc_sub
1922           ;
1923
1924 famc_sub  : famc_pedi_sect  /* 0:M */
1925           | note_struc_sub
1926           | no_std_sub
1927           ;
1928
1929 famc_pedi_sect : OPEN DELIM TAG_PEDI mand_line_item 
1930                  { START(PEDI, NULL) } no_std_subs { CHECK0 } CLOSE { }
1931                ;
1932
1933 /* CONTINUATION SUBSECTIONS */
1934 continuation_sub : cont_sect  /* 0:M */
1935                  | conc_sect  /* 0:M */
1936                  ;
1937
1938 cont_sect : OPEN DELIM TAG_CONT mand_line_item 
1939             { START(CONT, NULL) } no_std_subs { CHECK0 } CLOSE { }
1940           ;
1941
1942 conc_sect : OPEN DELIM TAG_CONC mand_line_item 
1943             { START(CONC, NULL) } no_std_subs { CHECK0 } CLOSE { }
1944           ; 
1945
1946 /* EVENT DETAIL */
1947 event_detail_sub : event_detail_type_sect  { OCCUR2(TYPE, 0, 1) }
1948                  | event_detail_date_sect  { OCCUR2(DATE, 0, 1) }
1949                  | place_struc_sub
1950                  | addr_struc_sub
1951                  | event_detail_age_sect  { OCCUR2(AGE, 0, 1) }
1952                  | event_detail_agnc_sect  { OCCUR2(AGNC, 0, 1) }
1953                  | event_detail_caus_sect  { OCCUR2(CAUS, 0, 1) }
1954                  | source_cit_sub
1955                  | multim_link_sub
1956                  | note_struc_sub
1957                  ;
1958
1959 event_detail_type_sect : OPEN DELIM TAG_TYPE mand_line_item 
1960                          { START(TYPE, NULL) } no_std_subs { CHECK0 } CLOSE { }
1961                        ;
1962 event_detail_date_sect : OPEN DELIM TAG_DATE mand_line_item 
1963                          { START(DATE, NULL) } no_std_subs { CHECK0 } CLOSE { }
1964                        ;
1965 event_detail_age_sect  : OPEN DELIM TAG_AGE mand_line_item 
1966                          { START(AGE, NULL) } no_std_subs { CHECK0 } CLOSE { }
1967                        ;
1968 event_detail_agnc_sect : OPEN DELIM TAG_AGNC mand_line_item 
1969                          { START(AGNC, NULL) } no_std_subs { CHECK0 } CLOSE { }
1970                        ;
1971 event_detail_caus_sect : OPEN DELIM TAG_CAUS mand_line_item 
1972                          { START(CAUS, NULL) } no_std_subs { CHECK0 } CLOSE { }
1973                        ;
1974
1975 /* FAMILY EVENT STRUCTURE */
1976 fam_event_struc_sub : fam_event_sect
1977                     | fam_gen_even_sect  /* 0:M */
1978                     ;
1979
1980 fam_event_sect : OPEN DELIM fam_event_tag opt_value fam_event_subs
1981                  { CHECK0 }
1982                  CLOSE { }
1983                ;
1984
1985 fam_event_tag : TAG_ANUL { START(ANUL, NULL) }
1986               | TAG_CENS { START(CENS, NULL) }
1987               | TAG_DIV { START(DIV, NULL) }
1988               | TAG_DIVF { START(DIVF, NULL) }
1989               | TAG_ENGA { START(ENGA, NULL) }
1990               | TAG_MARR { START(MARR, NULL) }
1991               | TAG_MARB { START(MARB, NULL) }
1992               | TAG_MARC { START(MARC, NULL) }
1993               | TAG_MARL { START(MARL, NULL) }
1994               | TAG_MARS { START(MARS, NULL) }
1995               ;
1996
1997 fam_event_subs : /* empty */
1998                | fam_event_subs fam_event_sub
1999                ;
2000
2001 fam_event_sub : event_detail_sub
2002               | fam_even_husb_sect  { OCCUR2(HUSB, 0, 1) }
2003               | fam_even_wife_sect  { OCCUR2(WIFE, 0, 1) }
2004               | no_std_sub
2005               ;
2006
2007 fam_even_husb_sect : OPEN DELIM TAG_HUSB
2008                      { START(HUSB, NULL) }
2009                      fam_even_husb_subs
2010                      { CHECK1(AGE) }
2011                      CLOSE { }
2012                    ;
2013
2014 fam_even_husb_subs : /* empty */
2015                    | fam_even_husb_subs fam_even_husb_sub
2016                    ;
2017
2018 fam_even_husb_sub : fam_even_husb_age_sect  { OCCUR2(AGE, 1, 1) }
2019                   | no_std_sub
2020                   ;
2021
2022 fam_even_husb_age_sect : OPEN DELIM TAG_AGE mand_line_item  
2023                          { START(AGE, NULL) } no_std_subs { CHECK0 } CLOSE { }
2024                        ;
2025
2026 fam_even_wife_sect : OPEN DELIM TAG_WIFE
2027                      { START(HUSB, NULL) }
2028                      fam_even_husb_subs
2029                      { CHECK1(AGE) }
2030                      CLOSE { }
2031                    ;
2032
2033 fam_gen_even_sect : OPEN DELIM TAG_EVEN
2034                     { START(EVEN, NULL) }
2035                     fam_gen_even_subs
2036                     { CHECK0 }
2037                     CLOSE { }
2038                   ;
2039
2040 fam_gen_even_subs : /* empty */
2041                   | fam_gen_even_subs fam_gen_even_sub
2042                   ;
2043
2044 fam_gen_even_sub : event_detail_sub
2045                  | fam_even_husb_sect  { OCCUR2(HUSB, 0, 1) }
2046                  | fam_even_wife_sect  { OCCUR2(WIFE, 0, 1) }
2047                  | no_std_sub
2048                  ;
2049
2050 /* IDENTIFICATION STRUCTURE */
2051 ident_struc_sub : ident_refn_sect  /* 0:M */
2052                 | ident_rin_sect  { OCCUR2(RIN, 0, 1) }
2053                 ;
2054
2055 ident_refn_sect : OPEN DELIM TAG_REFN mand_line_item 
2056                   { START(REFN, NULL) }
2057                   ident_refn_subs
2058                   { CHECK0 }
2059                   CLOSE { }
2060                 ;
2061
2062 ident_refn_subs : /* empty */
2063                 | ident_refn_subs ident_refn_sub
2064                 ;
2065
2066 ident_refn_sub  : ident_refn_type_sect  { OCCUR2(TYPE, 0, 1) }
2067                 | no_std_sub
2068                 ;
2069
2070 ident_refn_type_sect : OPEN DELIM TAG_TYPE mand_line_item   
2071                        { START(TYPE, NULL) } no_std_subs { CHECK0 } CLOSE { }
2072                      ;
2073
2074 ident_rin_sect  : OPEN DELIM TAG_RIN mand_line_item   
2075                   { START(RIN, NULL) } no_std_subs { CHECK0 } CLOSE { }
2076                 ;
2077
2078 /* INDIVIDUAL ATTRIBUTE STRUCTURE */
2079 indiv_attr_struc_sub : indiv_cast_sect  /* 0:M */
2080                      | indiv_dscr_sect  /* 0:M */
2081                      | indiv_educ_sect  /* 0:M */
2082                      | indiv_idno_sect  /* 0:M */
2083                      | indiv_nati_sect  /* 0:M */
2084                      | indiv_nchi_sect  /* 0:M */
2085                      | indiv_nmr_sect  /* 0:M */
2086                      | indiv_occu_sect  /* 0:M */
2087                      | indiv_prop_sect  /* 0:M */
2088                      | indiv_reli_sect  /* 0:M */
2089                      | indiv_resi_sect  /* 0:M */
2090                      | indiv_ssn_sect  /* 0:M */
2091                      | indiv_titl_sect  /* 0:M */
2092                      ;
2093
2094 indiv_cast_sect : OPEN DELIM TAG_CAST mand_line_item 
2095                   { START(CAST, NULL) }
2096                   indiv_attr_event_subs
2097                   { CHECK0 }
2098                   CLOSE { }
2099                 ;
2100 indiv_dscr_sect : OPEN DELIM TAG_DSCR mand_line_item 
2101                   { START(DSCR, NULL) }
2102                   indiv_attr_event_subs
2103                   { CHECK0 }
2104                   CLOSE { }
2105                 ;
2106 indiv_educ_sect : OPEN DELIM TAG_EDUC mand_line_item  
2107                   { START(EDUC, NULL) }
2108                   indiv_attr_event_subs 
2109                   { CHECK0 }
2110                   CLOSE { }
2111                 ;
2112 indiv_idno_sect : OPEN DELIM TAG_IDNO mand_line_item 
2113                   { START(IDNO, NULL) }
2114                   indiv_attr_event_subs 
2115                   { CHECK0 }
2116                   CLOSE { }
2117                 ;
2118 indiv_nati_sect : OPEN DELIM TAG_NATI mand_line_item 
2119                   { START(NATI, NULL) }
2120                   indiv_attr_event_subs 
2121                   { CHECK0 }
2122                   CLOSE { }
2123                 ;
2124 indiv_nchi_sect : OPEN DELIM TAG_NCHI mand_line_item 
2125                   { START(NCHI, NULL) }
2126                   indiv_attr_event_subs 
2127                   { CHECK0 }
2128                   CLOSE { }
2129                 ;
2130 indiv_nmr_sect  : OPEN DELIM TAG_NMR mand_line_item 
2131                   { START(NMR, NULL) }
2132                   indiv_attr_event_subs 
2133                   { CHECK0 }
2134                   CLOSE { }
2135                 ;
2136 indiv_occu_sect : OPEN DELIM TAG_OCCU mand_line_item 
2137                   { START(OCCU, NULL) }
2138                   indiv_attr_event_subs 
2139                   { CHECK0 }
2140                   CLOSE { }
2141                 ;
2142 indiv_prop_sect : OPEN DELIM TAG_PROP mand_line_item 
2143                   { START(PROP, NULL) }
2144                   indiv_attr_event_subs 
2145                   { CHECK0 }
2146                   CLOSE { }
2147                 ;
2148 indiv_reli_sect : OPEN DELIM TAG_RELI mand_line_item 
2149                   { START(RELI, NULL) }
2150                   indiv_attr_event_subs 
2151                   { CHECK0 }
2152                   CLOSE { }
2153                 ;
2154 indiv_resi_sect : OPEN DELIM TAG_RESI 
2155                   { START(RESI, NULL) }
2156                   indiv_attr_event_subs 
2157                   { CHECK0 }
2158                   CLOSE { }
2159                 ;
2160 indiv_ssn_sect  : OPEN DELIM TAG_SSN mand_line_item 
2161                   { START(SSN, NULL) }
2162                   indiv_attr_event_subs 
2163                   { CHECK0 }
2164                   CLOSE { }
2165                 ;
2166 indiv_titl_sect : OPEN DELIM TAG_TITL mand_line_item 
2167                   { START(TITL, NULL) }
2168                   indiv_attr_event_subs 
2169                   { CHECK0 }
2170                   CLOSE { }
2171                 ;
2172
2173 indiv_attr_event_subs : /* empty */
2174                       | indiv_attr_event_subs indiv_attr_event_sub
2175                       ;
2176
2177 indiv_attr_event_sub  : event_detail_sub
2178                       | no_std_sub
2179                       ;
2180
2181 /* INDIVIDUAL EVENT STRUCTURE */
2182 indiv_even_struc_sub : indiv_birt_sect
2183                      | indiv_gen_sect
2184                      | indiv_adop_sect  /* 0:M */
2185                      | indiv_even_sect  /* 0:M */
2186                      ;
2187
2188 indiv_birt_sect : OPEN DELIM indiv_birt_tag opt_value indiv_birt_subs
2189                   { CHECK0 }
2190                   CLOSE { }
2191                 ;
2192
2193 indiv_birt_tag  : TAG_BIRT { START(BIRT, NULL) }
2194                 | TAG_CHR { START(CHR, NULL) }
2195                 ;
2196
2197 indiv_birt_subs : /* empty */
2198                 | indiv_birt_subs indiv_birt_sub
2199                 ;
2200
2201 indiv_birt_sub  : event_detail_sub
2202                 | indiv_birt_famc_sect  { OCCUR2(FAMC,0, 1) }
2203                 | no_std_sub
2204                 ;
2205
2206 indiv_birt_famc_sect : OPEN DELIM TAG_FAMC mand_pointer
2207                        { START(FAMC, NULL) } no_std_subs { CHECK0 } CLOSE { }
2208                      ;
2209
2210 indiv_gen_sect  : OPEN DELIM indiv_gen_tag opt_value indiv_gen_subs
2211                   { CHECK0 }
2212                   CLOSE { }
2213                 ;
2214
2215 indiv_gen_tag   : TAG_DEAT { START(DEAT, NULL) }
2216                 | TAG_BURI { START(BURI, NULL) }
2217                 | TAG_CREM { START(CREM, NULL) }
2218                 | TAG_BAPM { START(BAPM, NULL) }
2219                 | TAG_BARM { START(BARM, NULL) }
2220                 | TAG_BASM { START(BASM, NULL) }
2221                 | TAG_BLES { START(BLES, NULL) }
2222                 | TAG_CHRA { START(CHRA, NULL) }
2223                 | TAG_CONF { START(CONF, NULL) }
2224                 | TAG_FCOM { START(FCOM, NULL) }
2225                 | TAG_ORDN { START(ORDN, NULL) }
2226                 | TAG_NATU { START(NATU, NULL) }
2227                 | TAG_EMIG { START(EMIG, NULL) }
2228                 | TAG_IMMI { START(IMMI, NULL) }
2229                 | TAG_CENS { START(CENS, NULL) }
2230                 | TAG_PROB { START(PROB, NULL) }
2231                 | TAG_WILL { START(WILL, NULL) }
2232                 | TAG_GRAD { START(GRAD, NULL) }
2233                 | TAG_RETI { START(RETI, NULL) }
2234                 ;
2235
2236 indiv_gen_subs  : /* empty */
2237                 | indiv_gen_subs indiv_gen_sub
2238                 ;
2239
2240 indiv_gen_sub   : event_detail_sub
2241                 | no_std_sub
2242                 ;
2243
2244 indiv_adop_sect : OPEN DELIM TAG_ADOP opt_value 
2245                   { START(ADOP, NULL) }
2246                   indiv_adop_subs
2247                   { CHECK0 }
2248                   CLOSE { }
2249                 ;
2250
2251 indiv_adop_subs : /* empty */
2252                 | indiv_adop_subs indiv_adop_sub
2253                 ;
2254
2255 indiv_adop_sub  : event_detail_sub
2256                 | indiv_adop_famc_sect  { OCCUR2(FAMC,0, 1) }
2257                 | no_std_sub
2258                 ;
2259
2260 indiv_adop_famc_sect : OPEN DELIM TAG_FAMC mand_pointer
2261                        { START(FAMC, NULL) }
2262                        indiv_adop_famc_subs
2263                        { CHECK0 }
2264                        CLOSE { }
2265                      ;
2266
2267 indiv_adop_famc_subs : /* empty */
2268                      | indiv_adop_famc_subs indiv_adop_famc_sub
2269                      ;
2270
2271 indiv_adop_famc_sub  : indiv_adop_famc_adop_sect  { OCCUR2(ADOP,0, 1) }
2272                      | no_std_sub
2273                      ;
2274
2275 indiv_adop_famc_adop_sect : OPEN DELIM TAG_ADOP mand_line_item   
2276                             { START(ADOP, NULL) } no_std_subs { CHECK0 } CLOSE { }
2277                           ;
2278
2279 indiv_even_sect : OPEN DELIM TAG_EVEN
2280                   { START(EVEN, NULL) }
2281                   indiv_gen_subs
2282                   { CHECK0 }
2283                   CLOSE { }
2284                 ;
2285
2286 /* LDS INDIVIDUAL ORDINANCE */
2287 lds_indiv_ord_sub : lio_bapl_sect  /* 0:M */
2288                   | lio_slgc_sect  /* 0:M */
2289                   ;
2290
2291 lio_bapl_sect : OPEN DELIM lio_bapl_tag lio_bapl_subs
2292                 { CHECK0 }
2293                 CLOSE { }
2294               ;
2295
2296 lio_bapl_tag  : TAG_BAPL { START(BAPL, NULL) }
2297               | TAG_CONL { START(CONL, NULL) }
2298               | TAG_ENDL { START(ENDL, NULL) }
2299               ;
2300
2301 lio_bapl_subs : /* empty */
2302               | lio_bapl_subs lio_bapl_sub
2303               ;
2304
2305 lio_bapl_sub  : lio_bapl_stat_sect  { OCCUR2(STAT, 0, 1) }
2306               | lio_bapl_date_sect  { OCCUR2(DATE, 0, 1) }
2307               | lio_bapl_temp_sect  { OCCUR2(TEMP, 0, 1) }
2308               | lio_bapl_plac_sect  { OCCUR2(PLAC, 0, 1) }
2309               | source_cit_sub
2310               | note_struc_sub
2311               | no_std_sub
2312               ;
2313
2314 lio_bapl_stat_sect : OPEN DELIM TAG_STAT mand_line_item   
2315                      { START(STAT, NULL) } no_std_subs { CHECK0 } CLOSE { }
2316                    ;
2317 lio_bapl_date_sect : OPEN DELIM TAG_DATE mand_line_item   
2318                      { START(DATE, NULL) } no_std_subs { CHECK0 } CLOSE { }
2319                    ;
2320 lio_bapl_temp_sect : OPEN DELIM TAG_TEMP mand_line_item   
2321                      { START(TEMP, NULL) } no_std_subs { CHECK0 } CLOSE { }
2322                    ;
2323 lio_bapl_plac_sect : OPEN DELIM TAG_PLAC mand_line_item   
2324                      { START(PLAC, NULL) } no_std_subs { CHECK0 } CLOSE { }
2325                    ;
2326
2327 lio_slgc_sect : OPEN DELIM TAG_SLGC
2328                 { START(SLGC, NULL) }
2329                 lio_slgc_subs
2330                 { CHECK1(FAMC) }
2331                 CLOSE { }
2332               ;
2333
2334 lio_slgc_subs : /* empty */
2335               | lio_slgc_subs lio_slgc_sub
2336               ;
2337
2338 lio_slgc_sub  : lio_bapl_sub
2339               | lio_slgc_famc_sect  { OCCUR2(FAMC, 1, 1) }
2340               ;
2341
2342 lio_slgc_famc_sect : OPEN DELIM TAG_FAMC mand_pointer
2343                      { START(FAMC, NULL) } no_std_subs { CHECK0 } CLOSE { }
2344                    ;
2345
2346 /* LDS SPOUSE SEALING */
2347 lds_spouse_seal_sub : lss_slgs_sect
2348                     ;
2349
2350 lss_slgs_sect : OPEN DELIM TAG_SLGS
2351                 { START(SLGS, NULL) }
2352                 lss_slgs_subs
2353                 { CHECK0 }
2354                 CLOSE { }
2355               ;
2356
2357 lss_slgs_subs : /* empty */
2358               | lss_slgs_subs lss_slgs_sub
2359               ;
2360
2361 lss_slgs_sub  : lss_slgs_stat_sect  { OCCUR2(STAT, 0, 1) }
2362               | lss_slgs_date_sect  { OCCUR2(DATE, 0, 1) }
2363               | lss_slgs_temp_sect  { OCCUR2(TEMP, 0, 1) }
2364               | lss_slgs_plac_sect  { OCCUR2(PLAC, 0, 1) }
2365               | source_cit_sub
2366               | note_struc_sub
2367               | no_std_sub
2368               ;
2369
2370 lss_slgs_stat_sect : OPEN DELIM TAG_STAT mand_line_item   
2371                      { START(STAT, NULL) } no_std_subs { CHECK0 } CLOSE { }
2372                    ;
2373 lss_slgs_date_sect : OPEN DELIM TAG_DATE mand_line_item   
2374                      { START(DATE, NULL) } no_std_subs { CHECK0 } CLOSE { }
2375                    ;
2376 lss_slgs_temp_sect : OPEN DELIM TAG_TEMP mand_line_item   
2377                      { START(TEMP, NULL) } no_std_subs { CHECK0 } CLOSE { }
2378                    ;
2379 lss_slgs_plac_sect : OPEN DELIM TAG_PLAC mand_line_item   
2380                      { START(PLAC, NULL) } no_std_subs { CHECK0 } CLOSE { }
2381                    ;
2382
2383 /* MULTIMEDIA LINK */
2384 multim_link_sub : multim_obje_link_sect
2385                 | multim_obje_emb_sect
2386                 ;
2387
2388 multim_obje_link_sect : OPEN DELIM TAG_OBJE DELIM POINTER    
2389                         { START(OBJE, NULL) } no_std_subs { CHECK0 } CLOSE { }
2390                       ;
2391
2392 multim_obje_emb_sect : OPEN DELIM TAG_OBJE
2393                        { START(OBJE, NULL) }
2394                        multim_obje_emb_subs
2395                        { CHECK2(FORM,FILE) }
2396                        CLOSE { }
2397                      ;
2398
2399 multim_obje_emb_subs : /* empty */
2400                      | multim_obje_emb_subs multim_obje_emb_sub
2401                      ;
2402
2403 multim_obje_emb_sub : multim_obje_form_sect  { OCCUR2(FORM, 1, 1) }
2404                     | multim_obje_titl_sect  { OCCUR2(TITL, 0, 1) }
2405                     | multim_obje_file_sect  { OCCUR2(FILE, 1, 1) }
2406                     | note_struc_sub
2407                     | no_std_sub
2408                     ;
2409
2410 multim_obje_form_sect : OPEN DELIM TAG_FORM mand_line_item    
2411                         { START(FORM, NULL) } no_std_subs { CHECK0 } CLOSE { }
2412                       ;
2413 multim_obje_titl_sect : OPEN DELIM TAG_TITL mand_line_item    
2414                         { START(TITL, NULL) } no_std_subs { CHECK0 } CLOSE { }
2415                       ;
2416 multim_obje_file_sect : OPEN DELIM TAG_FILE mand_line_item    
2417                         { START(FILE, NULL) } no_std_subs { CHECK0 } CLOSE { }
2418                       ;
2419
2420 /* NOTE STRUCTURE */
2421 note_struc_sub : note_struc_link_sect  /* 0:M */
2422                | note_struc_emb_sect  /* 0:M */
2423                ;
2424
2425 note_struc_link_sect : OPEN DELIM TAG_NOTE DELIM POINTER
2426                        { START(NOTE, NULL) }
2427                        note_struc_link_subs
2428                        { CHECK0 }
2429                        CLOSE { }
2430                      ;
2431
2432 note_struc_link_subs : /* empty */
2433                      | note_struc_link_subs note_struc_link_sub
2434                      ;
2435
2436 note_struc_link_sub : source_cit_sub
2437                     | no_std_sub
2438                     ;
2439
2440 note_struc_emb_sect : OPEN DELIM TAG_NOTE opt_line_item
2441                       { START(NOTE, NULL) }
2442                       note_struc_emb_subs
2443                       { CHECK0 }
2444                       CLOSE { }
2445                     ;
2446
2447 note_struc_emb_subs : /* empty */
2448                     | note_struc_emb_subs note_struc_emb_sub
2449                     ;
2450
2451 note_struc_emb_sub  : continuation_sub
2452                     | source_cit_sub
2453                     | no_std_sub
2454                     ;
2455
2456 /* PERSONAL NAME STRUCTURE */
2457 pers_name_struc_sub : pers_name_sect /* 0:M */
2458                     ;
2459
2460 pers_name_sect : OPEN DELIM TAG_NAME mand_line_item 
2461                  { START(NAME, NULL) }
2462                  pers_name_subs
2463                  { CHECK0 }
2464                  CLOSE { }
2465                ;
2466
2467 pers_name_subs : /* empty */
2468                | pers_name_subs pers_name_sub
2469                ;
2470
2471 pers_name_sub  : pers_name_npfx_sect  { OCCUR2(NPFX, 0, 1) }
2472                | pers_name_givn_sect  { OCCUR2(GIVN, 0, 1) }
2473                | pers_name_nick_sect  { OCCUR2(NICK, 0, 1) }
2474                | pers_name_spfx_sect  { OCCUR2(SPFX, 0, 1) }
2475                | pers_name_surn_sect  { OCCUR2(SURN, 0, 1) }
2476                | pers_name_nsfx_sect  { OCCUR2(NSFX, 0, 1) }
2477                | source_cit_sub
2478                | note_struc_sub
2479                | no_std_sub
2480                ;
2481
2482 pers_name_npfx_sect : OPEN DELIM TAG_NPFX mand_line_item    
2483                       { START(NPFX, NULL) } no_std_subs { CHECK0 } CLOSE { }
2484                     ;
2485 pers_name_givn_sect : OPEN DELIM TAG_GIVN mand_line_item    
2486                       { START(GIVN, NULL) } no_std_subs { CHECK0 } CLOSE { }
2487                     ;
2488 pers_name_nick_sect : OPEN DELIM TAG_NICK mand_line_item    
2489                       { START(NICK, NULL) } no_std_subs { CHECK0 } CLOSE { }
2490                     ;
2491 pers_name_spfx_sect : OPEN DELIM TAG_SPFX mand_line_item    
2492                       { START(SPFX, NULL) } no_std_subs { CHECK0 } CLOSE { }
2493                     ;
2494 pers_name_surn_sect : OPEN DELIM TAG_SURN mand_line_item    
2495                       { START(SURN, NULL) } no_std_subs { CHECK0 } CLOSE { }
2496                     ;
2497 pers_name_nsfx_sect : OPEN DELIM TAG_NSFX mand_line_item    
2498                       { START(NSFX, NULL) } no_std_subs { CHECK0 } CLOSE { }
2499                     ;
2500
2501 /* PLACE STRUCTURE */
2502 place_struc_sub : place_struc_plac_sect /* 0:M */
2503                 ;
2504
2505 place_struc_plac_sect : OPEN DELIM TAG_PLAC mand_line_item 
2506                         { START(PLAC, NULL) }
2507                         place_struc_plac_subs
2508                         { CHECK0 }
2509                         CLOSE { }
2510                       ;
2511
2512 place_struc_plac_subs : /* empty */
2513                       | place_struc_plac_subs place_struc_plac_sub
2514                       ;
2515
2516 place_struc_plac_sub : place_plac_form_sect  { OCCUR2(FORM, 0, 1) }
2517                      | source_cit_sub
2518                      | note_struc_sub
2519                      | no_std_sub
2520                      ;
2521
2522 place_plac_form_sect : OPEN DELIM TAG_FORM mand_line_item    
2523                        { START(FORM, NULL) } no_std_subs { CHECK0 } CLOSE { }
2524                      ;
2525
2526 /* SOURCE_CITATION */
2527 source_cit_sub : source_cit_link_sect /* 0:M */
2528                | source_cit_emb_sect /* 0:M */
2529                ;
2530
2531 source_cit_link_sect : OPEN DELIM TAG_SOUR DELIM POINTER
2532                        { START(SOUR, NULL) }
2533                        source_cit_link_subs
2534                        { CHECK0 }
2535                        CLOSE { }
2536                      ;
2537
2538 source_cit_link_subs : /* empty */
2539                      | source_cit_link_subs source_cit_link_sub
2540                      ;
2541
2542 source_cit_link_sub : source_cit_page_sect  { OCCUR2(PAGE, 0, 1) }
2543                     | source_cit_even_sect  { OCCUR2(EVEN, 0, 1) }
2544                     | source_cit_data_sect  { OCCUR2(DATA, 0, 1) }
2545                     | source_cit_quay_sect  { OCCUR2(QUAY, 0, 1) }
2546                     | multim_link_sub
2547                     | note_struc_sub
2548                     | no_std_sub
2549                     ;
2550
2551 source_cit_page_sect : OPEN DELIM TAG_PAGE mand_line_item    
2552                        { START(PAGE, NULL) } no_std_subs { CHECK0 } CLOSE { }
2553                      ;
2554
2555 source_cit_even_sect : OPEN DELIM TAG_EVEN mand_line_item 
2556                        { START(EVEN, NULL) }
2557                        source_cit_even_subs
2558                        { CHECK0 }
2559                        CLOSE { }
2560                      ;
2561
2562 source_cit_even_subs : /* empty */
2563                      | source_cit_even_subs source_cit_even_sub
2564                      ;
2565
2566 source_cit_even_sub  : source_cit_even_role_sect  { OCCUR2(ROLE, 0, 1) }
2567                      | no_std_sub
2568                      ;
2569
2570 source_cit_even_role_sect : OPEN DELIM TAG_ROLE mand_line_item    
2571                           { START(ROLE, NULL) } no_std_subs { CHECK0 } CLOSE { }
2572                           ;
2573
2574 source_cit_data_sect : OPEN DELIM TAG_DATA
2575                        { START(DATA, NULL) }
2576                        source_cit_data_subs
2577                        { CHECK0 }
2578                        CLOSE { }
2579                      ;
2580
2581 source_cit_data_subs : /* empty */
2582                      | source_cit_data_subs source_cit_data_sub
2583                      ;
2584
2585 source_cit_data_sub : source_cit_data_date_sect  { OCCUR2(DATE, 0, 1) }
2586                     | source_cit_text_sect  /* 0:M */
2587                     | no_std_sub
2588                     ;
2589
2590 source_cit_data_date_sect : OPEN DELIM TAG_DATE mand_line_item    
2591                             { START(DATE, NULL) } no_std_subs { CHECK0 } CLOSE { }
2592                           ;
2593
2594 source_cit_text_sect : OPEN DELIM TAG_TEXT mand_line_item 
2595                        { START(TEXT, NULL) }
2596                        source_cit_text_subs
2597                        { CHECK0 }
2598                        CLOSE { }
2599                      ;
2600
2601 source_cit_text_subs : /* empty */
2602                      | source_cit_text_subs source_cit_text_sub
2603                      ;
2604
2605 source_cit_text_sub : continuation_sub
2606                     | no_std_sub
2607                     ;
2608
2609 source_cit_quay_sect : OPEN DELIM TAG_QUAY mand_line_item    
2610                        { START(QUAY, NULL) } no_std_subs { CHECK0 } CLOSE { }
2611                      ;
2612
2613 source_cit_emb_sect : OPEN DELIM TAG_SOUR mand_line_item
2614                       { START(SOUR, NULL) }
2615                       source_cit_emb_subs
2616                       { CHECK0 }
2617                       CLOSE { }
2618                     ;
2619
2620 source_cit_emb_subs : /* empty */
2621                     | source_cit_emb_subs source_cit_emb_sub
2622                     ;
2623
2624 source_cit_emb_sub : continuation_sub
2625                    | source_cit_text_sect  /* 0:M */
2626                    | note_struc_sub
2627                    | no_std_sub
2628                    ;
2629
2630 /* SOURCE REPOSITORY CITATION */
2631 source_repos_cit_sub : source_repos_repo_sect  { OCCUR2(REPO, 0, 1) }
2632                      ;
2633
2634 source_repos_repo_sect : OPEN DELIM TAG_REPO mand_pointer
2635                          { START(REPO, NULL) }
2636                          source_repos_repo_subs
2637                          { CHECK0 }
2638                          CLOSE { }
2639                        ;
2640
2641 source_repos_repo_subs : /* empty */
2642                        | source_repos_repo_subs source_repos_repo_sub
2643                        ;
2644
2645 source_repos_repo_sub  : note_struc_sub
2646                        | caln_sect  /* 0:M */
2647                        | no_std_sub
2648                        ;
2649
2650 caln_sect : OPEN DELIM TAG_CALN mand_line_item 
2651             { START(CALN, NULL) }
2652             caln_subs
2653             { CHECK0 }
2654             CLOSE { }
2655           ;
2656
2657 caln_subs : /* empty */
2658           | caln_subs caln_sub
2659           ;
2660
2661 caln_sub  : caln_medi_sect  { OCCUR2(MEDI, 0, 1) }
2662           | no_std_sub
2663           ;
2664
2665 caln_medi_sect : OPEN DELIM TAG_MEDI mand_line_item    
2666                  { START(MEDI, NULL) } no_std_subs { CHECK0 } CLOSE { }
2667                ;
2668  
2669 /* SPOUSE TO FAMILY LINK */
2670 spou_fam_link_sub : spou_fam_fams_sect  /* 0:M */
2671                   ;
2672
2673 spou_fam_fams_sect : OPEN DELIM TAG_FAMS mand_pointer
2674                      { START(FAMS, NULL) }
2675                      spou_fam_fams_subs
2676                      { CHECK0 }
2677                      CLOSE { }
2678                    ;
2679
2680 spou_fam_fams_subs : /* empty */
2681                    | spou_fam_fams_subs spou_fam_fams_sub
2682                    ;
2683
2684 spou_fam_fams_sub  : note_struc_sub
2685                    | no_std_sub
2686                    ;
2687
2688 /*********************************************************************/
2689 /**** Special values                                              ****/
2690 /*********************************************************************/
2691
2692 /*********************************************************************/
2693 /**** General                                                     ****/
2694 /*********************************************************************/
2695
2696 no_std_subs : /* empty */
2697             | no_std_subs no_std_sub
2698             ;
2699
2700 no_std_sub  : user_sect /* 0:M */
2701             | gen_sect
2702             | error error_subs CLOSE  { HANDLE_ERROR }
2703             ;
2704
2705 no_std_rec  : user_rec /* 0:M */
2706             | gen_rec
2707             | error error_subs CLOSE  { HANDLE_ERROR }
2708             ;
2709
2710 user_rec    : OPEN DELIM opt_xref USERTAG 
2711               { if ($4[0] != '_') {
2712                   gedcom_error(_("Undefined tag (and not a valid user tag): %s"),
2713                                $4);
2714                   YYERROR;
2715                 }
2716               }
2717               opt_value
2718               { $<ctxt>$ = start_record(REC_USER, $1, $3, $4);
2719                 START($4, $<ctxt>$)
2720               }
2721               user_sects
2722               { CHECK0 }
2723               CLOSE
2724               { end_record(REC_USER, $<ctxt>7); }
2725             ;
2726 user_sect   : OPEN DELIM opt_xref USERTAG 
2727               { if ($4[0] != '_') {
2728                   gedcom_error(_("Undefined tag (and not a valid user tag): %s"),
2729                                $4);
2730                   YYERROR;
2731                 }
2732               }
2733               opt_value
2734               { $<ctxt>$ = start_element(ELT_USER, PARENT, $1, $4, $6,  
2735                                          GEDCOM_MAKE_STRING($6));
2736                 START($4, $<ctxt>$);
2737               }
2738               user_sects
2739               { CHECK0 }
2740               CLOSE
2741               { end_element(ELT_USER, PARENT, $<ctxt>7, NULL);
2742               }
2743             ;
2744
2745 user_sects   : /* empty */     { }
2746             | user_sects user_sect { }
2747             ;
2748
2749 opt_xref    : /* empty */        { $$ = NULL; }
2750             | POINTER DELIM        { $$ = $1; }
2751             ;
2752
2753 opt_value   : /* empty */        { $$ = NULL; }
2754             | DELIM line_value        { $$ = $2; }
2755             ;
2756
2757 line_value  : POINTER        { $$ = $1; }
2758             | line_item        { $$ = $1; }
2759             ;
2760
2761 mand_pointer : /* empty */ { gedcom_error(_("Missing pointer")); YYERROR; }
2762              | DELIM POINTER { gedcom_debug_print("==Ptr: %s==", $2);
2763                                $$ = $2; }
2764              ;
2765
2766 mand_line_item : /* empty */ { gedcom_error(_("Missing value")); YYERROR; }
2767                | DELIM line_item { gedcom_debug_print("==Val: %s==", $2);
2768                                    $$ = $2; }
2769                ;
2770
2771 opt_line_item : /* empty */ { }
2772               | DELIM line_item { }
2773               ;
2774
2775 line_item   : anychar  { size_t i;
2776                          CLEAR_BUFFER(line_item_buf);
2777                          line_item_buf_ptr = line_item_buf;
2778                          /* The following also takes care of '@@' */
2779                          if (!strncmp($1, "@@", 3))
2780                            *line_item_buf_ptr++ = '@';
2781                          else
2782                            for (i=0; i < strlen($1); i++)
2783                              *line_item_buf_ptr++ = $1[i];
2784                          $$ = line_item_buf;
2785                        }
2786             | ESCAPE   { CLEAR_BUFFER(line_item_buf);
2787                          line_item_buf_ptr = line_item_buf;
2788                          for (i=0; i < strlen($1); i++)
2789                            *line_item_buf_ptr++ = $1[i];
2790                          $$ = line_item_buf;
2791                        }
2792             | line_item anychar
2793                   { size_t i;
2794                     /* The following also takes care of '@@' */
2795                     if (!strncmp($2, "@@", 3))
2796                       *line_item_buf_ptr++ = '@';
2797                     else
2798                       for (i=0; i < strlen($2); i++)
2799                         *line_item_buf_ptr++ = $2[i];
2800                     $$ = line_item_buf;
2801                   }
2802             | line_item ESCAPE
2803                   { for (i=0; i < strlen($2); i++)
2804                       *line_item_buf_ptr++ = $2[i];
2805                     $$ = line_item_buf;
2806                   }
2807             ;
2808
2809 anychar     : ANYCHAR        { }
2810             | DELIM        { }
2811             ;
2812
2813 error_subs  : /* empty */
2814             | error_subs error_sect
2815             ;
2816
2817 error_sect  : OPEN DELIM opt_xref anytag opt_value error_subs CLOSE { }
2818
2819 gen_sect    : OPEN DELIM opt_xref anystdtag
2820               { INVALID_TAG($4); }
2821               opt_value opt_sects CLOSE
2822               { }
2823             ;
2824
2825 gen_rec : gen_rec_top
2826         | gen_rec_norm
2827         ;
2828
2829 gen_rec_norm : OPEN DELIM opt_xref anystdtag
2830                { INVALID_TOP_TAG($4) }
2831                opt_value opt_sects CLOSE
2832                { }
2833              ;
2834
2835 gen_rec_top : OPEN DELIM anytoptag
2836               { gedcom_error(_("Missing cross-reference")); YYERROR; }
2837               opt_value opt_sects CLOSE
2838                 { }
2839             ;
2840
2841 opt_sects   : /* empty */     { }
2842             | opt_sects gen_sect { }
2843             ;
2844
2845 anytag      : USERTAG { }
2846             | anystdtag { }
2847             ;
2848
2849 anytoptag   : TAG_FAM
2850             | TAG_INDI
2851             | TAG_OBJE
2852             | TAG_NOTE
2853             | TAG_REPO
2854             | TAG_SOUR
2855             | TAG_SUBN
2856             | TAG_SUBM
2857             ;
2858
2859 anystdtag   : TAG_ABBR
2860             | TAG_ADDR
2861             | TAG_ADR1
2862             | TAG_ADR2   { }
2863             | TAG_ADOP   { }
2864             | TAG_AFN   { }
2865             | TAG_AGE   { }
2866             | TAG_AGNC   { }
2867             | TAG_ALIA   { }
2868             | TAG_ANCE   { }
2869             | TAG_ANCI   { }
2870             | TAG_ANUL   { }
2871             | TAG_ASSO   { }
2872             | TAG_AUTH   { }
2873             | TAG_BAPL   { }
2874             | TAG_BAPM   { }
2875             | TAG_BARM   { }
2876             | TAG_BASM   { }
2877             | TAG_BIRT   { }
2878             | TAG_BLES   { }
2879             | TAG_BLOB   { }
2880             | TAG_BURI   { }
2881             | TAG_CALN   { }
2882             | TAG_CAST   { }
2883             | TAG_CAUS   { }
2884             | TAG_CENS   { }
2885             | TAG_CHAN   { }
2886             | TAG_CHAR   { }
2887             | TAG_CHIL   { }
2888             | TAG_CHR   { }
2889             | TAG_CHRA   { }
2890             | TAG_CITY   { }
2891             | TAG_CONC   { }
2892             | TAG_CONF   { }
2893             | TAG_CONL   { }
2894             | TAG_CONT   { }
2895             | TAG_COPR   { }
2896             | TAG_CORP   { }
2897             | TAG_CREM   { }
2898             | TAG_CTRY   { }
2899             | TAG_DATA   { }
2900             | TAG_DATE   { }
2901             | TAG_DEAT   { }
2902             | TAG_DESC   { }
2903             | TAG_DESI   { }
2904             | TAG_DEST   { }
2905             | TAG_DIV   { }
2906             | TAG_DIVF   { }
2907             | TAG_DSCR   { }
2908             | TAG_EDUC   { }
2909             | TAG_EMIG   { }
2910             | TAG_ENDL   { }
2911             | TAG_ENGA   { }
2912             | TAG_EVEN   { }
2913             | TAG_FAM    { }
2914             | TAG_FAMC   { }
2915             | TAG_FAMS   { }
2916             | TAG_FCOM   { }
2917             | TAG_FILE   { }
2918             | TAG_FORM   { }
2919             | TAG_GEDC   { }
2920             | TAG_GIVN   { }
2921             | TAG_GRAD   { }
2922             | TAG_HEAD   { }
2923             | TAG_HUSB   { }
2924             | TAG_IDNO   { }
2925             | TAG_IMMI   { }
2926             | TAG_INDI   { }
2927             | TAG_LANG   { }
2928             | TAG_LEGA   { }
2929             | TAG_MARB   { }
2930             | TAG_MARC   { }
2931             | TAG_MARL   { }
2932             | TAG_MARR   { }
2933             | TAG_MARS   { }
2934             | TAG_MEDI   { }
2935             | TAG_NAME   { }
2936             | TAG_NATI   { }
2937             | TAG_NCHI   { }
2938             | TAG_NICK   { }
2939             | TAG_NMR   { }
2940             | TAG_NOTE   { }
2941             | TAG_NPFX   { }
2942             | TAG_NSFX   { }
2943             | TAG_OBJE   { }
2944             | TAG_OCCU   { }
2945             | TAG_ORDI   { }
2946             | TAG_ORDN   { }
2947             | TAG_PAGE   { }
2948             | TAG_PEDI   { }
2949             | TAG_PHON   { }
2950             | TAG_PLAC   { }
2951             | TAG_POST   { }
2952             | TAG_PROB   { }
2953             | TAG_PROP   { }
2954             | TAG_PUBL   { }
2955             | TAG_QUAY   { }
2956             | TAG_REFN   { }
2957             | TAG_RELA   { }
2958             | TAG_RELI   { }
2959             | TAG_REPO   { }
2960             | TAG_RESI   { }
2961             | TAG_RESN   { }
2962             | TAG_RETI   { }
2963             | TAG_RFN   { }
2964             | TAG_RIN   { }
2965             | TAG_ROLE   { }
2966             | TAG_SEX   { }
2967             | TAG_SLGC   { }
2968             | TAG_SLGS   { }
2969             | TAG_SOUR   { }
2970             | TAG_SPFX   { }
2971             | TAG_SSN   { }
2972             | TAG_STAE   { }
2973             | TAG_STAT   { }
2974             | TAG_SUBM   { }
2975             | TAG_SUBN   { }
2976             | TAG_SURN   { }
2977             | TAG_TEMP   { }
2978             | TAG_TEXT   { }
2979             | TAG_TIME   { }
2980             | TAG_TITL   { }
2981             | TAG_TRLR   { }
2982             | TAG_TYPE   { }
2983             | TAG_VERS   { }
2984             | TAG_WIFE   { }
2985             | TAG_WILL   { }
2986
2987 %%
2988
2989 /* Functions that handle the counting of subtags */
2990
2991 int* count_arrays[MAXGEDCLEVEL+1];
2992 char tag_stack[MAXGEDCLEVEL+1][MAXSTDTAGLEN+1];
2993 Gedcom_ctxt ctxt_stack[MAXGEDCLEVEL+1];
2994
2995 void push_countarray()
2996 {
2997   int *count = NULL;
2998   if (count_level > MAXGEDCLEVEL) {
2999     gedcom_error(_("Internal error: count array overflow"));
3000     exit(1);
3001   }
3002   else {
3003     count = (int *)calloc(YYNTOKENS, sizeof(int));
3004     if (count == NULL) {
3005       gedcom_error(_("Internal error: count array calloc error"));
3006       exit(1);
3007     }
3008     else {
3009       count_arrays[count_level] = count;
3010     }
3011   }
3012 }
3013
3014 void set_parenttag(char* tag)
3015 {
3016   strncpy(tag_stack[count_level], tag, MAXSTDTAGLEN+1);
3017 }
3018
3019 void set_parentctxt(Gedcom_ctxt ctxt)
3020 {
3021   ctxt_stack[count_level] = ctxt;
3022 }
3023
3024 char* get_parenttag()
3025 {
3026   return tag_stack[count_level];
3027 }
3028
3029 Gedcom_ctxt get_parentctxt()
3030 {
3031   return ctxt_stack[count_level];
3032 }
3033
3034 int count_tag(int tag)
3035 {
3036   int *count = count_arrays[count_level];
3037   return ++count[tag - GEDCOMTAGOFFSET];
3038 }
3039
3040 int check_occurrence(int tag)
3041 {
3042   int *count = count_arrays[count_level];
3043   return (count[tag - GEDCOMTAGOFFSET] > 0);
3044 }
3045
3046 void pop_countarray()
3047 {
3048   int *count;
3049   if (count_level < 0) {
3050     gedcom_error(_("Internal error: count array underflow"));
3051     exit(1);
3052   }
3053   else {
3054     count = count_arrays[count_level];
3055     free(count);
3056     count_arrays[count_level] = NULL;
3057   }
3058 }
3059
3060 /* Enabling debug mode */
3061 /* level 0: no debugging */
3062 /* level 1: only internal */
3063 /* level 2: also bison */
3064 FILE* trace_output;
3065
3066 void gedcom_set_debug_level(int level, FILE* f)
3067 {
3068   if (f != NULL)
3069     trace_output = f;
3070   else
3071     trace_output = stderr;
3072   if (level > 0) {
3073     gedcom_high_level_debug = 1;
3074   }
3075   if (level > 1) {
3076 #if YYDEBUG != 0
3077     gedcom_debug = 1;
3078 #endif
3079   }
3080 }
3081
3082 int gedcom_debug_print(char* s, ...)
3083 {
3084   int res = 0;
3085   if (gedcom_high_level_debug) {
3086     va_list ap;
3087     va_start(ap, s);
3088     res = vfprintf(trace_output, s, ap);
3089     va_end(ap);
3090     fprintf(trace_output, "\n");
3091   }
3092   return(res);
3093 }
3094
3095 /* Setting the error mechanism */
3096 void gedcom_set_error_handling(Gedcom_err_mech mechanism)
3097 {
3098   error_mechanism = mechanism;
3099 }
3100
3101 /* Compatibility handling */
3102
3103 void gedcom_set_compat_handling(int enable_compat)
3104 {
3105   compat_enabled = enable_compat;
3106 }
3107
3108 void set_compatibility(char* program)
3109 {
3110   if (compat_enabled) {
3111     if (! strncmp(program, "ftree", 6)) {
3112       gedcom_warning(_("Enabling compatibility with 'ftree'"));
3113       compatibility = C_FTREE;
3114     }
3115     else {
3116       compatibility = 0;
3117     }
3118   }
3119 }
3120
3121 int compat_mode(int compat_flags)
3122 {
3123   return (compat_flags & compatibility);
3124 }
3125