From 809c37c2f87962cbb9fcb84c851d961e276fef72 Mon Sep 17 00:00:00 2001 From: Peter Verthez Date: Sat, 4 Jan 2003 18:46:54 +0000 Subject: [PATCH] Compatibility with Personal Ancestral File. --- gedcom/compat.c | 162 ++++++++++++++++++++++++++++++++++++++++-------- gedcom/compat.h | 9 ++- gedcom/gedcom.y | 59 +++++++++++++----- 3 files changed, 187 insertions(+), 43 deletions(-) diff --git a/gedcom/compat.c b/gedcom/compat.c index 8b5ed50..5bc93ed 100644 --- a/gedcom/compat.c +++ b/gedcom/compat.c @@ -25,6 +25,7 @@ #include "interface.h" #include "encoding.h" #include "xref.h" +#include "buffer.h" #include "gedcom_internal.h" #include "gedcom.h" @@ -33,13 +34,15 @@ int compatibility = 0; const char* default_charset = ""; #define SUBMITTER_LINK "@__COMPAT__SUBM__@" +#define SLGC_FAMC_LINK "@__COMPAT__FAM_SLGC__@" #define DEFAULT_SUBMITTER_NAME "Submitter" #define DEFAULT_GEDCOM_VERS "5.5" #define DEFAULT_GEDCOM_FORM "LINEAGE-LINKED" enum _COMPAT { C_FTREE = 0x01, - C_LIFELINES = 0x02 + C_LIFELINES = 0x02, + C_PAF = 0x04 }; /* Incompatibility list (with GEDCOM 5.5): @@ -56,6 +59,11 @@ enum _COMPAT { - HEAD.TIME instead of HEAD.DATE.TIME (will be ignored here) - '@' not written as '@@' in values - lots of missing required values + + - Personal Ancestral File: + - '@' not written as '@@' in values + - some 5.5.1 (draft) tags are used: EMAIL, FONE, ROMN + - no FAMC field in SLGC */ int compat_matrix[] = @@ -66,8 +74,26 @@ int compat_matrix[] = /* C_NO_GEDC */ C_LIFELINES, /* C_NO_CHAR */ C_LIFELINES, /* C_HEAD_TIME */ C_LIFELINES, - /* C_NO_DOUBLE_AT */ C_LIFELINES, - /* C_NO_REQUIRED_VALUES */ C_LIFELINES + /* C_NO_DOUBLE_AT */ C_LIFELINES | C_PAF, + /* C_NO_REQUIRED_VALUES */ C_LIFELINES, + /* C_551_TAGS */ C_PAF, + /* C_NO_SLGC_FAMC */ C_PAF, + /* C_NR_OF_RULES */ 0 +}; + +int compat_state[] = +{ + /* C_NO_SUBMITTER */ 0, + /* C_INDI_ADDR */ 0, + /* C_NOTE_NO_VALUE */ 0, + /* C_NO_GEDC */ 0, + /* C_NO_CHAR */ 0, + /* C_HEAD_TIME */ 0, + /* C_NO_DOUBLE_AT */ 0, + /* C_NO_REQUIRED_VALUES */ 0, + /* C_551_TAGS */ 0, + /* C_NO_SLGC_FAMC */ 0, + /* C_NR_OF_RULES */ 0 }; /* Compatibility handling */ @@ -77,23 +103,35 @@ void gedcom_set_compat_handling(int enable_compat) compat_enabled = enable_compat; } +void enable_compat_msg(const char* program_name) +{ + gedcom_warning(_("Enabling compatibility with '%s'"), program_name); +} + void set_compatibility(const char* program) { /* Reinitialize compatibility */ + int i; default_charset = ""; compatibility = 0; + for (i = 0; i < C_NR_OF_RULES; i++) + compat_state[i] = 0; if (compat_enabled) { if (! strncmp(program, "ftree", 6)) { - gedcom_warning(_("Enabling compatibility with 'ftree'")); + enable_compat_msg("ftree"); compatibility = C_FTREE; } else if (! strncmp(program, "LIFELINES", 9)) { /* Matches "LIFELINES 3.0.2" */ - gedcom_warning(_("Enabling compatibility with 'Lifelines'")); + enable_compat_msg("Lifelines"); compatibility = C_LIFELINES; default_charset = "ANSI"; } + else if (! strncmp(program, "PAF", 4)) { + enable_compat_msg("Personal Ancestral File"); + compatibility = C_PAF; + } } } @@ -111,36 +149,42 @@ void compat_generate_submitter_link(Gedcom_ctxt parent) ts.string = "SUBM"; ts.value = TAG_SUBM; + gedcom_warning(_("Adding link to submitter record with xref '%s'"), + SUBMITTER_LINK); self = start_element(ELT_HEAD_SUBM, parent, 1, ts, SUBMITTER_LINK, GEDCOM_MAKE_XREF_PTR(val1, xr)); end_element(ELT_HEAD_SUBM, parent, self, NULL); + compat_state[C_NO_SUBMITTER] = 1; } void compat_generate_submitter() { - struct xref_value *xr = gedcom_parse_xref(SUBMITTER_LINK, XREF_DEFINED, - XREF_SUBM); - struct tag_struct ts; - Gedcom_ctxt self1, self2; - - /* first generate "0 SUBM" */ - ts.string = "SUBM"; - ts.value = TAG_SUBM; - self1 = start_record(REC_SUBM, 0, GEDCOM_MAKE_XREF_PTR(val1, xr), ts, - NULL, GEDCOM_MAKE_NULL(val2)); - - /* then generate "1 NAME ..." */ - ts.string = "NAME"; - ts.value = TAG_NAME; - self2 = start_element(ELT_SUBM_NAME, self1, 1, ts, DEFAULT_SUBMITTER_NAME, - GEDCOM_MAKE_STRING(val1, DEFAULT_SUBMITTER_NAME)); - - /* close "1 NAME ..." */ - end_element(ELT_SUBM_NAME, self1, self2, NULL); - - /* close "0 SUBM" */ - end_record(REC_SUBM, self1, NULL); + if (compat_state[C_NO_SUBMITTER]) { + struct xref_value *xr = gedcom_parse_xref(SUBMITTER_LINK, XREF_DEFINED, + XREF_SUBM); + struct tag_struct ts; + Gedcom_ctxt self1, self2; + + /* first generate "0 SUBM" */ + ts.string = "SUBM"; + ts.value = TAG_SUBM; + self1 = start_record(REC_SUBM, 0, GEDCOM_MAKE_XREF_PTR(val1, xr), ts, + NULL, GEDCOM_MAKE_NULL(val2)); + + /* then generate "1 NAME ..." */ + ts.string = "NAME"; + ts.value = TAG_NAME; + self2 = start_element(ELT_SUBM_NAME, self1, 1, ts, DEFAULT_SUBMITTER_NAME, + GEDCOM_MAKE_STRING(val1, DEFAULT_SUBMITTER_NAME)); + + /* close "1 NAME ..." */ + end_element(ELT_SUBM_NAME, self1, self2, NULL); + + /* close "0 SUBM" */ + end_record(REC_SUBM, self1, NULL); + compat_state[C_NO_SUBMITTER] = 0; + } } void compat_generate_gedcom(Gedcom_ctxt parent) @@ -222,3 +266,67 @@ void compat_generate_resi_end(Gedcom_ctxt parent, Gedcom_ctxt self) { end_element(ELT_SUB_INDIV_RESI, parent, self, NULL); } + +int is_551_tag(const char* tag) +{ + if (strncmp(tag, "EMAIL", 6)) + return 1; + else if (strncmp(tag, "FONE", 5)) + return 1; + else if (strncmp(tag, "ROMN", 5)) + return 1; + else + return 0; +} + +int compat_check_551_tag(const char* tag, struct safe_buffer* b) +{ + if (is_551_tag(tag)) { + reset_buffer(b); + SAFE_BUF_ADDCHAR(b, '_'); + safe_buf_append(b, tag); + gedcom_warning(_("Converting 5.5.1 tag '%s' to standard 5.5 user tag '%s'"), + tag, get_buf_string(b)); + return 1; + } + else + return 0; +} + +void compat_generate_slgc_famc_link(Gedcom_ctxt parent) +{ + struct xref_value *xr = gedcom_parse_xref(SLGC_FAMC_LINK, XREF_USED, + XREF_FAM); + struct tag_struct ts; + Gedcom_ctxt self; + + ts.string = "FAMC"; + ts.value = TAG_FAMC; + gedcom_warning(_("Adding link to family record with xref '%s'"), + SLGC_FAMC_LINK); + self = start_element(ELT_SUB_LIO_SLGC_FAMC, + parent, 2, ts, SLGC_FAMC_LINK, + GEDCOM_MAKE_XREF_PTR(val1, xr)); + end_element(ELT_SUB_LIO_SLGC_FAMC, parent, self, NULL); + compat_state[C_NO_SLGC_FAMC]++; +} + +void compat_generate_slgc_famc_fam() +{ + /* If bigger than 1, then the FAM record has already been generated */ + if (compat_state[C_NO_SLGC_FAMC] == 1) { + struct xref_value *xr = gedcom_parse_xref(SLGC_FAMC_LINK, XREF_DEFINED, + XREF_FAM); + struct tag_struct ts; + Gedcom_ctxt self; + + /* generate "0 FAM" */ + ts.string = "FAM"; + ts.value = TAG_FAM; + self = start_record(REC_FAM, 0, GEDCOM_MAKE_XREF_PTR(val1, xr), ts, + NULL, GEDCOM_MAKE_NULL(val2)); + + /* close "0 FAM" */ + end_record(REC_FAM, self, NULL); + } +} diff --git a/gedcom/compat.h b/gedcom/compat.h index 03971d1..f5fc8f1 100644 --- a/gedcom/compat.h +++ b/gedcom/compat.h @@ -24,6 +24,7 @@ #ifndef __COMPAT_H #define __COMPAT_H +#include "buffer.h" #include "gedcom.h" typedef enum _COMPAT_RULES { @@ -34,7 +35,10 @@ typedef enum _COMPAT_RULES { C_NO_CHAR, C_HEAD_TIME, C_NO_DOUBLE_AT, - C_NO_REQUIRED_VALUES + C_NO_REQUIRED_VALUES, + C_551_TAGS, + C_NO_SLGC_FAMC, + C_NR_OF_RULES } Compat_rule; void set_compatibility(const char* program); @@ -45,5 +49,8 @@ void compat_generate_gedcom(Gedcom_ctxt parent); int compat_generate_char(Gedcom_ctxt parent); Gedcom_ctxt compat_generate_resi_start(Gedcom_ctxt parent); void compat_generate_resi_end(Gedcom_ctxt parent, Gedcom_ctxt self); +int compat_check_551_tag(const char* tag, struct safe_buffer* b); +void compat_generate_slgc_famc_link(Gedcom_ctxt parent); +void compat_generate_slgc_famc_fam(); #endif /* __COMPAT_H */ diff --git a/gedcom/gedcom.y b/gedcom/gedcom.y index 3e3667c..4a131b0 100644 --- a/gedcom/gedcom.y +++ b/gedcom/gedcom.y @@ -164,6 +164,10 @@ struct safe_buffer line_item_buffer = { NULL, 0, NULL, 0, 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); @@ -210,7 +214,9 @@ void clean_up(); #TAG, parenttag); \ HANDLE_ERROR; \ } \ - } + } +#define CHK_COND(TAG) \ + check_occurrence(TAG_##TAG) #define POP \ { pop_countarray(); \ --count_level; \ @@ -444,15 +450,15 @@ head_sect : OPEN DELIM TAG_HEAD NULL, GEDCOM_MAKE_NULL(val2)); START(HEAD, $1, $$) } head_subs - { if (compat_mode(C_NO_SUBMITTER)) + { if (compat_mode(C_NO_SUBMITTER) && ! CHK_COND(SUBM)) compat_generate_submitter_link($4); else CHK(SUBM); - if (compat_mode(C_NO_GEDC)) + if (compat_mode(C_NO_GEDC) && ! CHK_COND(GEDC)) compat_generate_gedcom($4); else CHK(GEDC); - if (compat_mode(C_NO_CHAR)) { + if (compat_mode(C_NO_CHAR) && ! CHK_COND(CHAR)) { if (compat_generate_char($4)) HANDLE_ERROR; } else CHK(CHAR); @@ -670,7 +676,7 @@ head_date_time_sect : OPEN DELIM TAG_TIME mand_line_item } ; -/* HEAD.TIME (Only for 'Lifelines' compatibility) */ +/* HEAD.TIME (Only for 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")); @@ -1049,7 +1055,10 @@ indiv_rec : OPEN DELIM POINTER DELIM TAG_INDI indi_subs { CHECK0 } CLOSE - { end_record(REC_INDI, $6, GEDCOM_MAKE_NULL(val1)); } + { end_record(REC_INDI, $6, GEDCOM_MAKE_NULL(val1)); + if (compat_mode(C_NO_SLGC_FAMC)) + compat_generate_slgc_famc_fam(); + } ; indi_subs : /* empty */ @@ -2885,7 +2894,11 @@ lio_slgc_sect : OPEN DELIM TAG_SLGC START(SLGC, $1, $$) } lio_slgc_subs - { CHECK1(FAMC) } + { if (compat_mode(C_NO_SLGC_FAMC) && ! CHK_COND(FAMC)) + compat_generate_slgc_famc_link($4); + else CHK(FAMC); + CHECK0; + } CLOSE { end_element(ELT_SUB_LIO_SLGC, PARENT, $4, GEDCOM_MAKE_NULL(val1)); @@ -3631,9 +3644,15 @@ no_std_rec : user_rec /* 0:M */ 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 @@ -3655,9 +3674,15 @@ user_rec : OPEN DELIM opt_xref USERTAG ; 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 { + gedcom_error(_("Undefined tag (and not a valid user tag): %s"), + $4); + YYERROR; + } } } opt_value @@ -3698,8 +3723,7 @@ mand_pointer : /* empty */ { gedcom_error(_("Missing pointer")); YYERROR; } 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: =="); $$ = ""; } else { @@ -4031,6 +4055,11 @@ void cleanup_line_item_buffer() cleanup_buffer(&line_item_buffer); } +void cleanup_usertag_buffer() +{ + cleanup_buffer(&usertag_buffer); +} + /* Enabling debug mode */ /* level 0: no debugging */ /* level 1: only internal */ -- 2.30.2