X-Git-Url: https://git.dlugolecki.net.pl/?a=blobdiff_plain;f=gedcom%2Fgedcom_date.y;h=79af990babef29e10739ac7c5fdfaec3744f3e53;hb=6103dd898c4de86c68891cc0222543988a2caab7;hp=282b8641ddaf69e2d8b9b4fc6050ef5c57f86a01;hpb=2fb61a5d3ffec21d16adfa03a89f01cd8235ccae;p=gedcom-parse.git diff --git a/gedcom/gedcom_date.y b/gedcom/gedcom_date.y index 282b864..79af990 100644 --- a/gedcom/gedcom_date.y +++ b/gedcom/gedcom_date.y @@ -24,6 +24,13 @@ %{ #include #include "date.h" +#include "compat.h" + +int _get_day_num(const char* input); +int _get_year_num(Year_type ytype, const char* input1, const char* input2); +void error_missing_year(); +void error_missing_month(); + %} %union { @@ -102,59 +109,70 @@ %% date_value : date { make_date_value(DV_NO_MODIFIER, - $1, def_date, ""); } + &$1, &def_date, ""); } | date_period | date_range | date_approx | date_interpr | date_phrase { make_date_value(DV_PHRASE, - def_date, def_date, $1); } + &def_date, &def_date, $1); } + | /* empty */ + { + /* If empty string: return empty string in 'phrase' + member as fallback */ + /* Note: this can only happen in compatibility mode */ + make_date_value(DV_PHRASE, + &def_date, &def_date, curr_line_value); + } | error { /* On error: put entire string in 'phrase' member as fallback */ + gedcom_date_error(_("Putting date '%s' in 'phrase' member"), curr_line_value); make_date_value(DV_PHRASE, - def_date, def_date, curr_line_value); } + &def_date, &def_date, curr_line_value); + YYABORT; + } ; -date : ESC_DATE_GREG date_greg { copy_date(&$$, date_s); +date : ESC_DATE_GREG date_greg { copy_date(&$$, &date_s); $$.cal = CAL_GREGORIAN; } - | ESC_DATE_JULN date_juln { copy_date(&$$, date_s); + | ESC_DATE_JULN date_juln { copy_date(&$$, &date_s); $$.cal = CAL_JULIAN; } - | ESC_DATE_HEBR date_hebr { copy_date(&$$, date_s); + | ESC_DATE_HEBR date_hebr { copy_date(&$$, &date_s); $$.cal = CAL_HEBREW; } - | ESC_DATE_FREN date_fren { copy_date(&$$, date_s); + | ESC_DATE_FREN date_fren { copy_date(&$$, &date_s); $$.cal = CAL_FRENCH_REV; } - | date_greg { copy_date(&$$, date_s); + | date_greg { copy_date(&$$, &date_s); $$.cal = CAL_GREGORIAN; } ; date_period : MOD_FROM date { make_date_value(DV_FROM, - $2, def_date, ""); } + &$2, &def_date, ""); } | MOD_TO date { make_date_value(DV_TO, - $2, def_date, ""); } - | MOD_FROM date { copy_date(&$$, $2); } + &$2, &def_date, ""); } + | MOD_FROM date { copy_date(&$$, &$2); } MOD_TO date - { make_date_value(DV_FROM_TO, $3, $5, ""); } + { make_date_value(DV_FROM_TO, &$3, &$5, ""); } ; date_range : MOD_BEF date { make_date_value(DV_BEFORE, - $2, def_date, ""); } + &$2, &def_date, ""); } | MOD_AFT date { make_date_value(DV_AFTER, - $2, def_date, ""); } - | MOD_BET date { copy_date(&$$, $2); } + &$2, &def_date, ""); } + | MOD_BET date { copy_date(&$$, &$2); } MOD_AND date - { make_date_value(DV_BETWEEN, $3, $5, ""); } + { make_date_value(DV_BETWEEN, &$3, &$5, ""); } ; date_approx : MOD_ABT date { make_date_value(DV_ABOUT, - $2, def_date, ""); } + &$2, &def_date, ""); } | MOD_CAL date { make_date_value(DV_CALCULATED, - $2, def_date, ""); } + &$2, &def_date, ""); } | MOD_EST date { make_date_value(DV_ESTIMATED, - $2, def_date, ""); } + &$2, &def_date, ""); } ; date_interpr : MOD_INT date date_phrase - { make_date_value(DV_INTERPRETED, $2, def_date, $3); } + { make_date_value(DV_INTERPRETED, &$2, &def_date, $3); } ; date_phrase : OPEN TEXT CLOSE { $$ = $2; } @@ -163,33 +181,43 @@ date_phrase : OPEN TEXT CLOSE { $$ = $2; } date_greg : day month_greg year_greg | month_greg year_greg | year_greg + | day month_greg { error_missing_year(); YYERROR; } + | month_greg { error_missing_year(); YYERROR; } + | day year_greg { error_missing_month(); YYERROR; } ; date_juln : day month_greg year | month_greg year | year + | day month_greg { error_missing_year(); YYERROR; } + | month_greg { error_missing_year(); YYERROR; } + | day year_greg { error_missing_month(); YYERROR; } ; date_hebr : day month_hebr year | month_hebr year | year + | day month_hebr { error_missing_year(); YYERROR; } + | month_hebr { error_missing_year(); YYERROR; } + | day year { error_missing_month(); YYERROR; } ; date_fren : day month_fren year | month_fren year | year + | day month_hebr { error_missing_year(); YYERROR; } + | month_hebr { error_missing_year(); YYERROR; } + | day year { error_missing_month(); YYERROR; } ; day : NUMBER { - if (strlen($1) <= MAX_DAY_LEN) { + int d = _get_day_num($1); + if (d != -1) { strcpy(date_s.day_str, $1); - date_s.day = atoi($1); - } - else { - gedcom_date_error(_("Too many characters in day '%s'"), - $1); + date_s.day = d; } + else YYERROR; } ; @@ -276,41 +304,149 @@ month_fren : MON_VEND { strcpy(date_s.month_str, $1); ; year : NUMBER - { if (strlen($1) <= MAX_YEAR_LEN) { + { int y = _get_year_num(YEAR_SINGLE, $1, NULL); + if (y != -1) { strcpy(date_s.year_str, $1); - date_s.year = atoi($1); + date_s.year = y; date_s.year_type = YEAR_SINGLE; } - else { - gedcom_date_error(_("Too many characters in year '%s'"), - $1); - } + else YYERROR; } ; year_greg : NUMBER - { if (strlen($1) <= MAX_YEAR_LEN) { + { int y = _get_year_num(YEAR_SINGLE, $1, NULL); + if (y != -1) { strcpy(date_s.year_str, $1); - date_s.year = atoi($1); + date_s.year = y; date_s.year_type = YEAR_SINGLE; } - else { - gedcom_date_error(_("Too many characters in year '%s'"), - $1); - } + else YYERROR; } | NUMBER SLASH NUMBER - { if (strlen($1) + strlen($3) + 1 <= MAX_YEAR_LEN) { - sprintf(date_s.year_str, "%s/%s", $1, $3); - date_s.year = atoi($1) + 1; - date_s.year_type = YEAR_DOUBLE; + { if (compat_double_date_check($3)) { + safe_buf_append(&compat_buffer, "BET %s AND %s", + $1, $3); } else { - gedcom_date_error(_("Too many characters in year '%s/%s'"), - $1, $3); + int y = _get_year_num(YEAR_DOUBLE, $1, $3); + if (y != -1) { + sprintf(date_s.year_str, "%d/%02d", y-1, y%100); + date_s.year = y; + date_s.year_type = YEAR_DOUBLE; + } + else YYERROR; } - } ; %% + +void error_missing_year() +{ + gedcom_date_error(_("Year is missing: '%s'"), + curr_line_value); +} + +void error_missing_month() +{ + gedcom_date_error(_("Month is missing: '%s'"), + curr_line_value); +} + +int _get_day_num(const char* input) +{ + if (strlen(input) <= MAX_DAY_LEN) + return atoi(input); + else { + gedcom_date_error(_("Too many characters in day '%s'"), input); + return -1; + } +} + +int get_day_num(const char* input) +{ + int token = get_date_token(input); + if (token == NUMBER) + return _get_day_num(input); + else { + gedcom_date_error(_("Not a valid day number: '%s'"), input); + return -1; + } +} + +int begin_month[] = +{ /* CAL_GREGORIAN */ MON_JAN, + /* CAL_JULIAN */ MON_JAN, + /* CAL_HEBREW */ MON_TSH, + /* CAL_FRENCH_REV */ MON_VEND +}; + +int end_month[] = +{ /* CAL_GREGORIAN */ MON_DEC, + /* CAL_JULIAN */ MON_DEC, + /* CAL_HEBREW */ MON_ELL, + /* CAL_FRENCH_REV */ MON_COMP +}; + +int get_month_num(Calendar_type cal, const char* input) +{ + int token = get_date_token(input); + if (token >= begin_month[cal] && token <= end_month[cal]) + return token - begin_month[cal] + 1; + else { + gedcom_date_error(_("Not a valid month for the given calendar: '%s'"), + input); + return -1; + } +} + +int _get_year_num(Year_type ytype, const char* input1, const char* input2) +{ + if (ytype == YEAR_SINGLE) { + if (strlen(input1) <= MAX_YEAR_LEN) { + return atoi(input1); + } + else { + gedcom_date_error(_("Too many characters in year '%s'"), input1); + return -1; + } + } + else { + if (strlen(input2) != 2) { + gedcom_date_error(_("Year after slash should be two digits: '%s/%s'"), + input1, input2); + return -1; + } + if (strlen(input1) <= MAX_YEAR_LEN - 3) { + int year1 = atoi(input1) + 1; + int year2 = atoi(input2); + if (year1 % 100 != year2) { + gedcom_date_error(_("Year after slash should be following year: '%s/%s'"), + input1, input2); + return -1; + } + else + return year1; + } + else { + gedcom_date_error(_("Too many characters in year '%s/%s'"), + input1, input2); + return -1; + } + } +} + +int get_year_num(const char* input, Year_type* ytype) +{ + char *year1, *year2 = NULL; + int numtok = get_year_tokens(input, &year1, &year2); + if (numtok) { + *ytype = (numtok == 1 ? YEAR_SINGLE : YEAR_DOUBLE); + return _get_year_num (*ytype, year1, year2); + } + else { + gedcom_date_error(_("Not a valid year: '%s'"), input); + return -1; + } +}