source_event.c \
source_description.c \
user_rec.c \
- gom_modify.c
+ gom_modify.c \
+ gom_internal.c
noinst_HEADERS = header.h \
submission.h \
submitter.h \
else {
struct address *addr = SUB_MAKEFUNC(address)();
if (addr) {
- switch (ctxt->ctxt_type) {
+ int type = ctxt_type(ctxt);
+ switch (type) {
case ELT_HEAD_SOUR_CORP:
ADDFUNC2_NOLIST(header,address)(ctxt, addr); break;
case ELT_SUB_FAM_EVT:
case REC_SUBM:
ADDFUNC2_NOLIST(submitter,address)(ctxt, addr); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, address, addr);
}
if (! ctxt)
NO_CONTEXT;
else {
- result = make_gom_ctxt(elt, ctxt->ctxt_type, ctxt->ctxt_ptr);
+ result = dup_gom_ctxt(ctxt, elt);
}
return (Gedcom_ctxt)result;
}
NO_CONTEXT;
else {
char *str = GEDCOM_STRING(parsed_value);
- switch (ctxt->ctxt_type) {
+ int type = ctxt_type(ctxt);
+ switch (type) {
case ELT_HEAD_SOUR_CORP:
header_add_phone(ctxt, str); break;
case ELT_SUB_FAM_EVT:
case REC_SUBM:
submitter_add_phone(ctxt, str); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
- result = make_gom_ctxt(elt, ctxt->obj_type, ctxt->ctxt_ptr);
+ result = dup_gom_ctxt(ctxt, elt);
}
return (Gedcom_ctxt)result;
}
else {
struct association *assoc = SUB_MAKEFUNC(association)();
if (assoc) {
+ int type = ctxt_type(ctxt);
assoc->to = GEDCOM_XREF_PTR(parsed_value);
-
- switch (ctxt->ctxt_type) {
+
+ switch (type) {
case REC_INDI:
ADDFUNC2(individual,association)(ctxt, assoc);
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, association, assoc);
}
else {
struct change_date *chan = SUB_MAKEFUNC(change_date)();
if (chan) {
- switch (ctxt->ctxt_type) {
+ int type = ctxt_type(ctxt);
+ switch (type) {
case REC_FAM:
ADDFUNC2_NOLIST(family,change_date)(ctxt, chan); break;
case REC_INDI:
case REC_SUBM:
ADDFUNC2_NOLIST(submitter,change_date)(ctxt, chan); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, change_date, chan);
}
}
if (! err) {
- switch (ctxt->ctxt_type) {
+ int type = ctxt_type(ctxt);
+ switch (type) {
case REC_FAM:
ADDFUNC2(family,event)(ctxt, evt); break;
case REC_INDI:
ADDFUNC2(individual,event)(ctxt, evt); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, event, evt);
}
}
if (! err) {
- switch (ctxt->ctxt_type) {
+ int type = ctxt_type(ctxt);
+ switch (type) {
case REC_INDI:
ADDFUNC2_TOVAR(individual,event,attribute)(ctxt, evt); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, event, evt);
}
if (evt) {
int err = 0;
struct age_value age = GEDCOM_AGE(parsed_value);
- switch (ctxt->ctxt_type) {
+ int type = ctxt_type(ctxt);
+ switch (type) {
case ELT_SUB_FAM_EVT_HUSB:
evt->husband_age = gedcom_new_age_value(&age);
if (! evt->husband_age) {
}
break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
if (! err)
result = MAKE_GOM_CTXT(elt, event, evt);
else {
struct family_link *link = SUB_MAKEFUNC(family_link)();
if (link) {
+ int type = ctxt_type(ctxt);
link->family = GEDCOM_XREF_PTR(parsed_value);
- switch (ctxt->ctxt_type) {
+ switch (type) {
case REC_INDI:
ADDFUNC2(individual,family_link)(ctxt, elt, link); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, family_link, link);
}
else \
obj->FIELD = newvalue; \
} \
- destroy_gom_ctxt(ctxt); \
+ def_elt_end(elt, parent, self, parsed_value); \
} \
}
else \
obj->FIELD = newvalue; \
} \
- destroy_gom_ctxt(ctxt); \
+ def_rec_end(rec, self, parsed_value); \
} \
}
level, tag, raw_value);
}
+void gom_mem_error(const char *filename, int line)
+{
+ gedcom_error(_("Could not allocate memory at %s, %d"), filename, line);
+}
+
+void gom_xref_already_in_use(const char *xrefstr)
+{
+ gedcom_error(_("Cross-reference key '%s' is already in use"), xrefstr);
+}
+
+void gom_move_error(const char* type)
+{
+ gedcom_warning(_("Could not move struct of type %s"), type);
+}
+
+void gom_find_error(const char* type)
+{
+ gedcom_warning(_("Could not find struct of type %s in chain"), type);
+}
+
void set_xref_type(struct xref_value* xr, const char *str)
{
if (!strcasecmp(str, "FAM"))
"association", "source_event", "source_description"
};
+/* Assumptions for context:
+ - In case of error, NULL is passed as context
+ - If not NULL, the ctxt_ptr of the context is not NULL also
+ - UNEXPECTED_CONTEXT is not treated as an error, but as a warning
+
+ The context chain keeps contexts until the end of the record, so that
+ elements out of context can be handled.
+*/
+
+struct Gom_ctxt_struct {
+ int ctxt_type;
+ OBJ_TYPE obj_type;
+ void* ctxt_ptr;
+ struct Gom_ctxt_struct* next;
+};
+
+struct Gom_ctxt_struct* ctxt_chain = NULL;
+
Gom_ctxt make_gom_ctxt(int ctxt_type, OBJ_TYPE obj_type, void *ctxt_ptr)
{
Gom_ctxt ctxt = (Gom_ctxt)malloc(sizeof(struct Gom_ctxt_struct));
ctxt->ctxt_type = ctxt_type;
ctxt->obj_type = obj_type;
ctxt->ctxt_ptr = ctxt_ptr;
+ ctxt->next = ctxt_chain;
+ ctxt_chain = ctxt;
}
return ctxt;
}
+Gom_ctxt dup_gom_ctxt(Gom_ctxt ctxt, int ctxt_type)
+{
+ return make_gom_ctxt(ctxt_type, ctxt->obj_type, ctxt->ctxt_ptr);
+}
+
+int ctxt_type(Gom_ctxt ctxt)
+{
+ return ctxt->ctxt_type;
+}
+
+OBJ_TYPE ctxt_obj_type(Gom_ctxt ctxt)
+{
+ return ctxt->obj_type;
+}
+
+void* safe_ctxt_cast(Gom_ctxt ctxt, OBJ_TYPE type, const char* file, int line)
+{
+ if (ctxt->obj_type != type) {
+ gom_cast_error(file, line, type, ctxt->obj_type);
+ }
+ return ctxt->ctxt_ptr;
+}
+
void NULL_DESTROY(void* anything UNUSED)
{
}
abort();
}
-void gom_mem_error(const char *filename, int line)
-{
- gedcom_error(_("Could not allocate memory at %s, %d"), filename, line);
-}
-
-void gom_xref_already_in_use(const char *xrefstr)
-{
- gedcom_error(_("Cross-reference key '%s' is already in use"), xrefstr);
-}
-
void gom_unexpected_context(const char* file, int line, OBJ_TYPE found)
{
const char* found_name = "<out-of-bounds>";
file, line);
}
-void gom_move_error(const char* type)
-{
- gedcom_warning(_("Could not move struct of type %s"), type);
-}
-
-void gom_find_error(const char* type)
-{
- gedcom_warning(_("Could not find struct of type %s in chain"), type);
-}
-
-void def_rec_end(Gedcom_rec rec UNUSED, Gedcom_ctxt self,
+void def_rec_end(Gedcom_rec rec UNUSED, Gedcom_ctxt self UNUSED,
Gedcom_val parsed_value UNUSED)
{
- Gom_ctxt ctxt = (Gom_ctxt)self;
- destroy_gom_ctxt(ctxt);
+ Gom_ctxt ctxt;
+ while (ctxt_chain) {
+ ctxt = ctxt_chain;
+ ctxt_chain = ctxt->next;
+ destroy_gom_ctxt(ctxt);
+ }
}
-/* TODO: do this in a way so that elements out of context can be handled */
void def_elt_end(Gedcom_elt elt UNUSED, Gedcom_ctxt parent UNUSED,
- Gedcom_ctxt self, Gedcom_val parsed_value UNUSED)
+ Gedcom_ctxt self UNUSED, Gedcom_val parsed_value UNUSED)
{
- Gom_ctxt ctxt = (Gom_ctxt)self;
- destroy_gom_ctxt(ctxt);
}
T_LAST
} OBJ_TYPE;
-/* Assumptions for context:
- - In case of error, NULL is passed as context
- - If not NULL, the ctxt_ptr of the context is not NULL also
- - UNEXPECTED_CONTEXT is not treated as an error, but as a warning
-*/
-
-struct Gom_ctxt_struct {
- int ctxt_type;
- OBJ_TYPE obj_type;
- void* ctxt_ptr;
-};
-
+struct Gom_ctxt_struct;
typedef struct Gom_ctxt_struct *Gom_ctxt;
Gom_ctxt make_gom_ctxt(int ctxt_type, OBJ_TYPE obj_type, void *ctxt_ptr);
-void destroy_gom_ctxt(Gom_ctxt ctxt);
+Gom_ctxt dup_gom_ctxt(Gom_ctxt ctxt, int ctxt_type);
+void* safe_ctxt_cast(Gom_ctxt ctxt, OBJ_TYPE type, const char* file, int line);
+int ctxt_type(Gom_ctxt ctxt);
+OBJ_TYPE ctxt_obj_type(Gom_ctxt ctxt);
+
void gom_cast_error(const char* file, int line,
OBJ_TYPE expected, OBJ_TYPE found);
void gom_no_context(const char* file, int line);
make_gom_ctxt(CTXT_TYPE, T_ ## STRUCTTYPE, CTXT_PTR)
#define SAFE_CTXT_CAST(STRUCTTYPE, VAL) \
- (((VAL)->obj_type == T_ ## STRUCTTYPE) ? \
- (VAL)->ctxt_ptr : \
- (gom_cast_error(__FILE__, __LINE__, T_ ## STRUCTTYPE, (VAL)->obj_type), \
- (VAL)->ctxt_ptr))
+ safe_ctxt_cast(VAL, T_ ## STRUCTTYPE, __FILE__, __LINE__)
#define SAFE_FREE(PTR) \
if (PTR) { \
free(lds_evt);
}
else {
- switch (ctxt->ctxt_type) {
+ int type = ctxt_type(ctxt);
+ switch (type) {
case REC_FAM:
ADDFUNC2(family,lds_event)(ctxt, lds_evt); break;
case REC_INDI:
ADDFUNC2(individual,lds_event)(ctxt, lds_evt); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, lds_event, lds_evt);
}
if (! ctxt)
NO_CONTEXT;
else
- result = make_gom_ctxt(elt, ctxt->obj_type, ctxt->ctxt_ptr);
+ result = dup_gom_ctxt(ctxt, elt);
return (Gedcom_ctxt)result;
}
else {
struct multimedia_link *mm = SUB_MAKEFUNC(multimedia_link)();
if (mm) {
+ int type = ctxt_type(ctxt);
if (GEDCOM_IS_XREF_PTR(parsed_value))
mm->reference = GEDCOM_XREF_PTR(parsed_value);
- switch (ctxt->ctxt_type) {
+ switch (type) {
case ELT_SUB_FAM_EVT:
case ELT_SUB_FAM_EVT_EVEN:
case ELT_SUB_INDIV_ATTR:
case REC_SUBM:
ADDFUNC2(submitter,multimedia_link)(ctxt, mm); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, multimedia_link, mm);
}
if (! ctxt)
NO_CONTEXT;
else
- result = make_gom_ctxt(elt, ctxt->obj_type, ctxt->ctxt_ptr);
+ result = dup_gom_ctxt(ctxt, elt);
return (Gedcom_ctxt)result;
}
else {
struct note_sub *note = SUB_MAKEFUNC(note_sub)();
if (note) {
+ int type = ctxt_type(ctxt);
if (GEDCOM_IS_XREF_PTR(parsed_value))
note->reference = GEDCOM_XREF_PTR(parsed_value);
- switch (ctxt->ctxt_type) {
+ switch (type) {
case ELT_SUB_PLAC:
ADDFUNC2(place,note_sub)(ctxt, note); break;
case ELT_SUB_FAM_EVT:
case REC_SOUR:
ADDFUNC2(source,note_sub)(ctxt, note); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, note_sub, note);
}
free(name);
}
else {
- switch (ctxt->ctxt_type) {
+ int type = ctxt_type(ctxt);
+ switch (type) {
case REC_INDI:
ADDFUNC2(individual,personal_name)(ctxt, name); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, personal_name, name);
}
free(place);
}
else {
- switch (ctxt->ctxt_type) {
+ int type = ctxt_type(ctxt);
+ switch (type) {
case ELT_SUB_FAM_EVT:
case ELT_SUB_FAM_EVT_EVEN:
case ELT_SUB_INDIV_ATTR:
case ELT_SUB_INDIV_EVEN:
ADDFUNC2_NOLIST(event,place)(ctxt, place); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, place, place);
}
else {
struct source_citation *cit = SUB_MAKEFUNC(source_citation)();
if (cit) {
+ int type = ctxt_type(ctxt);
if (GEDCOM_IS_XREF_PTR(parsed_value))
cit->reference = GEDCOM_XREF_PTR(parsed_value);
- switch (ctxt->ctxt_type) {
+ switch (type) {
case ELT_SUB_PLAC:
ADDFUNC2(place,source_citation)(ctxt, cit); break;
case ELT_SUB_FAM_EVT:
case REC_NOTE:
ADDFUNC2(note,source_citation)(ctxt, cit); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, source_citation, cit);
}
free(desc);
}
else {
- switch (ctxt->ctxt_type) {
+ int type = ctxt_type(ctxt);
+ switch (type) {
case ELT_SUB_REPO:
ADDFUNC2(source,source_description)(ctxt, desc); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, source_description, desc);
}
free(evt);
}
else {
- switch (ctxt->ctxt_type) {
+ int type = ctxt_type(ctxt);
+ switch (type) {
case ELT_SOUR_DATA:
ADDFUNC2(source,source_event)(ctxt, evt); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, source_event, evt);
}
data->xref_value = GEDCOM_XREF_PTR(parsed_value);
if (! err) {
- switch (ctxt->obj_type) {
+ switch (ctxt_obj_type(ctxt)) {
case T_header:
ADDFUNC2(header,user_data)(ctxt, data); break;
case T_submission:
case T_source_description:
ADDFUNC2(source_description,user_data)(ctxt, data); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(ctxt_type(ctxt));
}
- result = make_gom_ctxt(elt, ctxt->obj_type, ctxt->ctxt_ptr);
+ result = dup_gom_ctxt(ctxt, elt);
}
}
}
free(refn);
}
else {
- switch (ctxt->ctxt_type) {
+ int type = ctxt_type(ctxt);
+ switch (type) {
case REC_FAM:
ADDFUNC2(family,user_ref_number)(ctxt, refn); break;
case REC_INDI:
case REC_SOUR:
ADDFUNC2(source,user_ref_number)(ctxt, refn); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
result = MAKE_GOM_CTXT(elt, user_ref_number, refn);
NO_CONTEXT;
else {
char *str = GEDCOM_STRING(parsed_value);
+ int type = ctxt_type(ctxt);
- switch (ctxt->ctxt_type) {
+ switch (type) {
case REC_FAM:
ADDFUNC2_STR(family,record_id)(ctxt, str); break;
case REC_INDI:
case REC_SOUR:
ADDFUNC2_STR(source,record_id)(ctxt, str); break;
default:
- UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+ UNEXPECTED_CONTEXT(type);
}
- result = make_gom_ctxt(elt, ctxt->obj_type, ctxt->ctxt_ptr);
+ result = dup_gom_ctxt(ctxt, elt);
}
return (Gedcom_ctxt)result;
}