1 /* Cross-reference manipulation routines.
2 Copyright (C) 2001,2002 The Genes Development Team
3 This file is part of the Gedcom parser library.
4 Contributed by Peter Verthez <Peter.Verthez@advalvas.be>, 2001.
6 The Gedcom parser library is free software; you can redistribute it
7 and/or modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The Gedcom parser library is distributed in the hope that it will be
12 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the Gedcom parser library; if not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 #include "gedcom_internal.h"
28 struct xref_value def_xref_val = { XREF_NONE, "<error>", NULL };
29 static hash_t *xrefs = NULL;
31 char* xref_type_str[] = { N_("nothing"),
35 N_("a multimedia object"),
36 N_("a source repository"),
39 N_("a submission record"),
40 N_("an application-specific record"),
44 struct xref_value xref;
45 Xref_type defined_type;
51 hnode_t *xref_alloc(void *c __attribute__((unused)))
53 return malloc(sizeof *xref_alloc(NULL));
56 void xref_free(hnode_t *n, void *c __attribute__((unused)))
58 struct xref_node *xr = (struct xref_node *)hnode_get(n);
59 free((void*)hnode_getkey(n));
60 free(xr->xref.string);
65 struct xref_node *make_xref_node()
67 struct xref_node *xr = (struct xref_node *)malloc(sizeof(struct xref_node));
68 xr->xref.type = XREF_NONE;
69 xr->xref.string = NULL;
70 xr->xref.object = NULL;
71 xr->defined_type = XREF_NONE;
72 xr->used_type = XREF_NONE;
73 xr->defined_line = -1;
78 void make_xref_table()
80 xrefs = hash_create(HASHCOUNT_T_MAX, NULL, NULL);
81 hash_set_allocator(xrefs, xref_alloc, xref_free, NULL);
84 int check_xref_table()
91 /* Check for undefined and unused xrefs */
92 hash_scan_begin(&hs, xrefs);
93 while ((node = hash_scan_next(&hs))) {
94 xr = (struct xref_node *)hnode_get(node);
95 if (xr->defined_type == XREF_NONE && xr->used_type != XREF_NONE) {
96 gedcom_error(_("Cross-reference %s used on line %d is not defined"),
97 xr->xref.string, xr->used_line);
100 if (xr->used_type == XREF_NONE && xr->defined_type != XREF_NONE) {
101 gedcom_warning(_("Cross-reference %s defined on line %d is never used"),
102 xr->xref.string, xr->defined_line);
110 struct xref_value *gedcom_parse_xref(char *raw_value,
111 Xref_ctxt ctxt, Xref_type xref_type)
113 struct xref_node *xr = NULL;
115 hnode_t *node = hash_lookup(xrefs, raw_value);
117 xr = (struct xref_node *)hnode_get(node);
120 char *key = strdup(raw_value);
121 xr = make_xref_node();
122 xr->xref.type = xref_type;
123 xr->xref.string = strdup(raw_value);
124 hash_alloc_insert(xrefs, key, xr);
127 if (ctxt == XREF_DEFINED && xr->defined_type == XREF_NONE) {
128 xr->defined_type = xref_type;
129 xr->defined_line = line_no;
131 else if (ctxt == XREF_USED && xr->used_type == XREF_NONE) {
132 xr->used_type = xref_type;
133 xr->used_line = line_no;
136 if ((ctxt == XREF_DEFINED && xr->defined_type != xref_type)
137 || (ctxt == XREF_USED &&
138 (xr->defined_type != XREF_NONE && xr->defined_type != xref_type))) {
139 gedcom_error(_("Cross-reference %s previously defined as pointer to %s, "
141 xr->xref.string, xref_type_str[xr->defined_type],
146 if ((ctxt == XREF_USED && xr->used_type != xref_type)
147 || (ctxt == XREF_DEFINED &&
148 (xr->used_type != XREF_NONE && xr->used_type != xref_type))) {
149 gedcom_error(_("Cross-reference %s previously used as pointer to %s, "
151 xr->xref.string, xref_type_str[xr->used_type], xr->used_line);