void cleanup_concat_buffer();
struct safe_buffer concat_buffer = { NULL, 0, NULL, 0, cleanup_concat_buffer };
+
+void cleanup_usertag_buffer();
+struct safe_buffer usertag_buffer = { NULL, 0, NULL, 0,
+ cleanup_usertag_buffer};
/* These are defined at the bottom of the file */
void push_countarray(int level);
void pop_countarray();
int count_tag(int tag);
int check_occurrence(int tag);
-void clean_up();
+void clean_up();
#define HANDLE_ERROR \
{ if (error_mechanism == IMMED_FAIL) { \
#TAG, parenttag); \
HANDLE_ERROR; \
} \
- }
+ }
+#define CHK_COND(TAG) \
+ check_occurrence(TAG_##TAG)
#define POP \
{ pop_countarray(); \
--count_level; \
}
%token_table
-%expect 308
+%expect 309
%token <string> BADTOKEN
%token <number> OPEN
NULL, GEDCOM_MAKE_NULL(val2));
START(HEAD, $1, $<ctxt>$) }
head_subs
- { if (compat_mode(C_NO_SUBMITTER))
+ { if (compat_mode(C_NO_SUBMITTER) && ! CHK_COND(SUBM))
compat_generate_submitter_link($<ctxt>4);
else CHK(SUBM);
- if (compat_mode(C_NO_GEDC))
+ if (compat_mode(C_NO_GEDC) && ! CHK_COND(GEDC))
compat_generate_gedcom($<ctxt>4);
else CHK(GEDC);
- if (compat_mode(C_NO_CHAR)) {
+ if (compat_mode(C_NO_CHAR) && ! CHK_COND(CHAR)) {
if (compat_generate_char($<ctxt>4)) HANDLE_ERROR;
}
else CHK(CHAR);
/* HEAD.SOUR */
head_sour_sect : OPEN DELIM TAG_SOUR mand_line_item
- { set_compatibility($4);
+ { set_compatibility_program($4);
$<ctxt>$ = start_element(ELT_HEAD_SOUR, PARENT,
$1, $3, $4,
GEDCOM_MAKE_STRING(val1, $4));
head_sour_subs
{ CHECK0 }
CLOSE
- { end_element(ELT_HEAD_SOUR, PARENT, $<ctxt>5,
+ { compute_compatibility();
+ end_element(ELT_HEAD_SOUR, PARENT, $<ctxt>5,
GEDCOM_MAKE_NULL(val1)); }
;
;
head_sour_vers_sect : OPEN DELIM TAG_VERS mand_line_item
- { $<ctxt>$ = start_element(ELT_HEAD_SOUR_VERS, PARENT,
+ { set_compatibility_version($4);
+ $<ctxt>$ = start_element(ELT_HEAD_SOUR_VERS, PARENT,
$1, $3, $4,
GEDCOM_MAKE_STRING(val1, $4));
START(VERS, $1, $<ctxt>$)
$<ctxt>$ = start_element(ELT_HEAD_DATE,
PARENT, $1, $3, $4,
GEDCOM_MAKE_DATE(val1, dv));
+ if (compat_mode(C_HEAD_TIME))
+ compat_save_head_date_context($<ctxt>$);
START(DATE, $1, $<ctxt>$)
}
head_date_subs
}
;
-/* HEAD.TIME (Only for 'Lifelines' compatibility) */
-/* Just ignore the time... */
-head_time_sect : OPEN DELIM TAG_TIME opt_line_item CLOSE
- { gedcom_warning(_("Header change time lost in the compatibility"));
+/* HEAD.TIME (Only for compatibility) */
+head_time_sect : OPEN DELIM TAG_TIME opt_line_item
+ { if (compat_mode(C_HEAD_TIME)) {
+ $<ctxt>$ = compat_generate_head_time_start($1, $3, $4);
+ }
+ }
+ CLOSE
+ { if (compat_mode (C_HEAD_TIME)) {
+ compat_generate_head_time_end($<ctxt>5);
+ }
}
;
START(GEDC, $1, $<ctxt>$)
}
head_gedc_subs
- { CHECK2(VERS, FORM) }
+ { if (compat_mode(C_NO_GEDC_FORM) && ! CHK_COND(FORM))
+ compat_generate_gedcom_form($<ctxt>4);
+ else CHK(FORM);
+
+ CHECK1(VERS)
+ }
+
CLOSE
{ end_element(ELT_HEAD_GEDC, PARENT, $<ctxt>4,
GEDCOM_MAKE_NULL(val1));
indi_subs
{ CHECK0 }
CLOSE
- { end_record(REC_INDI, $<ctxt>6, GEDCOM_MAKE_NULL(val1)); }
+ { end_record(REC_INDI, $<ctxt>6, GEDCOM_MAKE_NULL(val1));
+ if (compat_mode(C_NO_SLGC_FAMC))
+ compat_generate_slgc_famc_fam();
+ }
;
indi_subs : /* empty */
= start_element(ELT_SUB_ADDR,
par, $1 + 1, $3, $4,
GEDCOM_MAKE_NULL_OR_STRING(val2, $4));
+ reset_buffer(&concat_buffer);
+ safe_buf_append(&concat_buffer, $4);
START(ADDR, $1 + 1, $<ctxt>$);
}
else { START(ADDR, $1, NULL) }
CLOSE
{ if (compat_mode(C_INDI_ADDR)) {
Gedcom_ctxt par = PARENT;
+ char* complete = get_buf_string(&concat_buffer);
end_element(ELT_SUB_ADDR, par, $<ctxt>5,
- GEDCOM_MAKE_NULL(val1));
+ GEDCOM_MAKE_STRING(val1, complete));
CHECK0;
compat_generate_resi_end(PARENT, par);
}
gedcom_error(_("Missing value")); YYERROR;
}
else {
- $$ = "";
+ $$ = VALUE_IF_MISSING;
}
}
| DELIM line_item
| source_cit_sub /* 0:M */
| ident_struc_sub /* 0:1 */
| change_date_sub /* 0:1 */
+ | note_note_sect { if (!compat_mode(C_NOTE_NOTE))
+ INVALID_TAG("NOTE");
+ }
| no_std_sub
;
+/* Same actions as cont_sect, for compatibility */
+note_note_sect : OPEN DELIM TAG_NOTE opt_line_item
+ { $3.string = "CONT";
+ $3.value = TAG_CONT;
+ $<ctxt>$ = start_element(ELT_SUB_CONT,
+ PARENT, $1, $3, $4,
+ GEDCOM_MAKE_NULL_OR_STRING(val1, $4));
+ SAFE_BUF_ADDCHAR(&concat_buffer, '\n');
+ if (GEDCOM_IS_STRING(&val1))
+ safe_buf_append(&concat_buffer, $4);
+ START(CONT, $1, $<ctxt>$)
+ }
+ no_std_subs
+ { CHECK0 }
+ CLOSE
+ { end_element(ELT_SUB_CONT, PARENT, $<ctxt>5,
+ GEDCOM_MAKE_NULL(val1));
+ }
+ ;
+
/*********************************************************************/
/**** Repository record ****/
/*********************************************************************/
| conc_sect /* 0:M */
;
-cont_sect : OPEN DELIM TAG_CONT mand_line_item
+cont_sect : OPEN DELIM TAG_CONT opt_line_item
{ $<ctxt>$ = start_element(ELT_SUB_CONT,
PARENT, $1, $3, $4,
- GEDCOM_MAKE_STRING(val1, $4));
+ GEDCOM_MAKE_NULL_OR_STRING(val1, $4));
SAFE_BUF_ADDCHAR(&concat_buffer, '\n');
- safe_buf_append(&concat_buffer, $4);
+ if (GEDCOM_IS_STRING(&val1))
+ safe_buf_append(&concat_buffer, $4);
START(CONT, $1, $<ctxt>$)
}
no_std_subs
{ $<ctxt>$ = start_element(ELT_SUB_CONC,
PARENT, $1, $3, $4,
GEDCOM_MAKE_STRING(val1, $4));
+ if (compat_mode(C_CONC_NEEDS_SPACE)) {
+ safe_buf_append(&concat_buffer, " ");
+ }
safe_buf_append(&concat_buffer, $4);
START(CONC, $1, $<ctxt>$)
}
START(SLGC, $1, $<ctxt>$)
}
lio_slgc_subs
- { CHECK1(FAMC) }
+ { if (compat_mode(C_NO_SLGC_FAMC) && ! CHK_COND(FAMC))
+ compat_generate_slgc_famc_link($<ctxt>4);
+ else CHK(FAMC);
+ CHECK0;
+ }
CLOSE
{ end_element(ELT_SUB_LIO_SLGC, PARENT, $<ctxt>4,
GEDCOM_MAKE_NULL(val1));
user_rec : OPEN DELIM opt_xref USERTAG
{ if ($4.string[0] != '_') {
- gedcom_error(_("Undefined tag (and not a valid user tag): %s"),
- $4);
- YYERROR;
+ if (compat_mode(C_551_TAGS)
+ && compat_check_551_tag($4.string, &usertag_buffer)) {
+ $4.string = get_buf_string(&usertag_buffer);
+ }
+ else {
+ gedcom_error(_("Undefined tag (and not a valid user tag): %s"),
+ $4);
+ YYERROR;
+ }
}
}
opt_value
;
user_sect : OPEN DELIM opt_xref USERTAG
{ if ($4.string[0] != '_') {
- gedcom_error(_("Undefined tag (and not a valid user tag): %s"),
- $4);
- YYERROR;
+ if (compat_mode(C_551_TAGS)
+ && compat_check_551_tag($4.string, &usertag_buffer)) {
+ $4.string = get_buf_string(&usertag_buffer);
+ }
+ else if (compat_mode(C_SUBM_COMM) &&
+ compat_check_subm_comm($4.string, get_parenttag(0),
+ &usertag_buffer)) {
+ $4.string = get_buf_string(&usertag_buffer);
+ }
+ else {
+ gedcom_error(_("Undefined tag (and not a valid user tag): %s"),
+ $4);
+ YYERROR;
+ }
}
}
opt_value
CLOSE
{ end_element(ELT_USER, PARENT, $<ctxt>7,
GEDCOM_MAKE_NULL(val1));
+ if (compat_mode(C_SUBM_COMM))
+ compat_close_subm_comm();
}
;
user_sects : /* empty */ { }
| user_sects user_sect { }
+ | user_sects gen_sect
+ { if (compat_mode(C_SUBM_COMM)) {
+ }
+ else {
+ gedcom_error(_("Standard tag not allowed in user section"));
+ YYERROR;
+ }
+ }
;
opt_xref : /* empty */ { $$ = NULL; }
mand_line_item : /* empty */
{ if (compat_mode(C_NO_REQUIRED_VALUES)) {
- /* Lifelines tends to not care about mandatory values */
- gedcom_debug_print("==Val: ==");
- $$ = "";
+ gedcom_debug_print("==Val: ==");
+ $$ = VALUE_IF_MISSING;
}
else {
gedcom_error(_("Missing value")); YYERROR;
;
gen_sect : OPEN DELIM opt_xref anystdtag
- { INVALID_TAG($4.string); }
- opt_value opt_sects CLOSE
- { }
+ { if (compat_mode(C_SUBM_COMM)
+ && compat_check_subm_comm_cont($4.string)) {
+ /* Will pass here */
+ }
+ else {
+ INVALID_TAG($4.string);
+ }
+ }
+ opt_value
+ { if (compat_mode(C_SUBM_COMM)) {
+ $<ctxt>$ = compat_subm_comm_cont_start(PARENT, $6);
+ }
+ }
+ opt_sects CLOSE
+ { if (compat_mode(C_SUBM_COMM))
+ compat_subm_comm_cont_end(PARENT, $<ctxt>7);
+ }
;
gen_rec : gen_rec_top
void push_countarray(int level)
{
int *count = NULL;
- gedcom_debug_print("Push Count level: %d, level: %d\n", count_level, level);
+ gedcom_debug_print("Push Count level: %d, level: %d", count_level, level);
if (count_level != level + 1) {
gedcom_error(_("Internal error: count level mismatch"));
exit(1);
exit(1);
}
else {
- gedcom_debug_print("calloc countarray %d\n", count_level);
+ gedcom_debug_print("calloc countarray %d", count_level);
count = (int *)calloc(YYNTOKENS, sizeof(int));
if (count == NULL) {
gedcom_error(_("Internal error: count array calloc error"));
void pop_countarray()
{
int *count;
- gedcom_debug_print("Pop Count level: %d\n", count_level);
+ gedcom_debug_print("Pop Count level: %d", count_level);
if (count_level < 0) {
gedcom_error(_("Internal error: count array underflow"));
exit(1);
}
else {
count = count_arrays[count_level];
- gedcom_debug_print("free countarray %d\n", count_level);
+ gedcom_debug_print("free countarray %d", count_level);
free(count);
count_arrays[count_level] = NULL;
}
void clean_up()
{
- gedcom_debug_print("Cleanup countarrays\n");
+ gedcom_debug_print("Cleanup countarrays");
while (count_level > 0) {
pop_countarray();
--count_level;
cleanup_buffer(&line_item_buffer);
}
+void cleanup_usertag_buffer()
+{
+ cleanup_buffer(&usertag_buffer);
+}
+
/* Enabling debug mode */
/* level 0: no debugging */
/* level 1: only internal */