+struct xref_node* add_xref(Xref_type xref_type, const char* xrefstr,
+ Gedcom_ctxt object)
+{
+ struct xref_node *xr = NULL;
+ char *key = strdup(xrefstr);
+ if (key) {
+ xr = make_xref_node();
+ xr->xref.type = xref_type;
+ xr->xref.object = object;
+ if (xr->xref.string)
+ free(xr->xref.string);
+ xr->xref.string = strdup(xrefstr);
+ if (! xr->xref.string) {
+ MEMORY_ERROR;
+ free(key);
+ delete_xref_node(xr);
+ xr = NULL;
+ }
+ else {
+ hash_alloc_insert(xrefs, key, xr);
+ }
+ }
+ else
+ MEMORY_ERROR;
+ return xr;
+}
+
+void remove_xref(struct xref_node* xr)
+{
+ hnode_t *node = hash_lookup(xrefs, xr->xref.string);
+ hash_delete_free(xrefs, node);
+}
+
+int set_xref_fields(struct xref_node* xr, Xref_ctxt ctxt, Xref_type xref_type)
+{
+ int result = 0;
+
+ if (xr->defined_type != XREF_NONE && xr->defined_type != xref_type &&
+ xr->defined_type != XREF_ANY) {
+ if (xr->defined_line != 0)
+ gedcom_error(_("Cross-reference %s previously defined as pointer to %s, "
+ "on line %d"),
+ xr->xref.string, xref_type_str[xr->defined_type],
+ xr->defined_line);
+ else
+ gedcom_error(_("Cross-reference %s previously defined as pointer to %s"),
+ xr->xref.string, xref_type_str[xr->defined_type]);
+
+ result = 1;
+ }
+ else if (xr->used_type != XREF_NONE && xr->used_type != xref_type) {
+ if (xr->used_line != 0)
+ gedcom_error(_("Cross-reference %s previously used as pointer to %s, "
+ "on line %d"),
+ xr->xref.string, xref_type_str[xr->used_type],
+ xr->used_line);
+ else
+ gedcom_error(_("Cross-reference %s previously used as pointer to %s"),
+ xr->xref.string, xref_type_str[xr->used_type]);
+
+ result = 1;
+ }
+
+ if (result == 0) {
+ if (ctxt == XREF_USED)
+ xr->use_count++;
+ if (ctxt == XREF_DEFINED && xr->defined_type == XREF_NONE) {
+ xr->defined_type = xref_type;
+ xr->defined_line = line_no;
+ }
+ else if (ctxt == XREF_USED && xr->used_type == XREF_NONE) {
+ xr->used_type = xref_type;
+ xr->used_line = line_no;
+ }
+ }
+
+ return result;
+}
+
+struct xref_value *gedcom_parse_xref(const char *raw_value,