xref: /freebsd/contrib/mandoc/mandoc_xr.c (revision 6d38604fc532a3fc060788e3ce40464b46047eaf)
1*6d38604fSBaptiste Daroussin /* $Id: mandoc_xr.c,v 1.4 2020/06/22 19:20:40 schwarze Exp $ */
261d06d6bSBaptiste Daroussin /*
361d06d6bSBaptiste Daroussin  * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
461d06d6bSBaptiste Daroussin  *
561d06d6bSBaptiste Daroussin  * Permission to use, copy, modify, and distribute this software for any
661d06d6bSBaptiste Daroussin  * purpose with or without fee is hereby granted, provided that the above
761d06d6bSBaptiste Daroussin  * copyright notice and this permission notice appear in all copies.
861d06d6bSBaptiste Daroussin  *
961d06d6bSBaptiste Daroussin  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1061d06d6bSBaptiste Daroussin  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1161d06d6bSBaptiste Daroussin  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1261d06d6bSBaptiste Daroussin  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1361d06d6bSBaptiste Daroussin  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1461d06d6bSBaptiste Daroussin  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1561d06d6bSBaptiste Daroussin  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1661d06d6bSBaptiste Daroussin  */
17*6d38604fSBaptiste Daroussin #include "config.h"
18*6d38604fSBaptiste Daroussin 
1961d06d6bSBaptiste Daroussin #include <sys/types.h>
2061d06d6bSBaptiste Daroussin 
2161d06d6bSBaptiste Daroussin #include <assert.h>
2261d06d6bSBaptiste Daroussin #include <stddef.h>
2361d06d6bSBaptiste Daroussin #include <stdint.h>
2461d06d6bSBaptiste Daroussin #include <stdlib.h>
2561d06d6bSBaptiste Daroussin #include <string.h>
2661d06d6bSBaptiste Daroussin 
2761d06d6bSBaptiste Daroussin #include "mandoc_aux.h"
2861d06d6bSBaptiste Daroussin #include "mandoc_ohash.h"
2961d06d6bSBaptiste Daroussin #include "mandoc_xr.h"
3061d06d6bSBaptiste Daroussin 
3161d06d6bSBaptiste Daroussin static struct ohash	 *xr_hash = NULL;
3261d06d6bSBaptiste Daroussin static struct mandoc_xr	 *xr_first = NULL;
3361d06d6bSBaptiste Daroussin static struct mandoc_xr	 *xr_last = NULL;
3461d06d6bSBaptiste Daroussin 
3561d06d6bSBaptiste Daroussin static void		  mandoc_xr_clear(void);
3661d06d6bSBaptiste Daroussin 
3761d06d6bSBaptiste Daroussin 
3861d06d6bSBaptiste Daroussin static void
mandoc_xr_clear(void)3961d06d6bSBaptiste Daroussin mandoc_xr_clear(void)
4061d06d6bSBaptiste Daroussin {
4161d06d6bSBaptiste Daroussin 	struct mandoc_xr	*xr;
4261d06d6bSBaptiste Daroussin 	unsigned int		 slot;
4361d06d6bSBaptiste Daroussin 
4461d06d6bSBaptiste Daroussin 	if (xr_hash == NULL)
4561d06d6bSBaptiste Daroussin 		return;
4661d06d6bSBaptiste Daroussin 	for (xr = ohash_first(xr_hash, &slot); xr != NULL;
4761d06d6bSBaptiste Daroussin 	     xr = ohash_next(xr_hash, &slot))
4861d06d6bSBaptiste Daroussin 		free(xr);
4961d06d6bSBaptiste Daroussin 	ohash_delete(xr_hash);
5061d06d6bSBaptiste Daroussin }
5161d06d6bSBaptiste Daroussin 
5261d06d6bSBaptiste Daroussin void
mandoc_xr_reset(void)5361d06d6bSBaptiste Daroussin mandoc_xr_reset(void)
5461d06d6bSBaptiste Daroussin {
5561d06d6bSBaptiste Daroussin 	if (xr_hash == NULL)
5661d06d6bSBaptiste Daroussin 		xr_hash = mandoc_malloc(sizeof(*xr_hash));
5761d06d6bSBaptiste Daroussin 	else
5861d06d6bSBaptiste Daroussin 		mandoc_xr_clear();
5961d06d6bSBaptiste Daroussin 	mandoc_ohash_init(xr_hash, 5,
6061d06d6bSBaptiste Daroussin 	    offsetof(struct mandoc_xr, hashkey));
6161d06d6bSBaptiste Daroussin 	xr_first = xr_last = NULL;
6261d06d6bSBaptiste Daroussin }
6361d06d6bSBaptiste Daroussin 
6461d06d6bSBaptiste Daroussin int
mandoc_xr_add(const char * sec,const char * name,int line,int pos)6561d06d6bSBaptiste Daroussin mandoc_xr_add(const char *sec, const char *name, int line, int pos)
6661d06d6bSBaptiste Daroussin {
6761d06d6bSBaptiste Daroussin 	struct mandoc_xr	 *xr, *oxr;
6861d06d6bSBaptiste Daroussin 	const char		 *pend;
6961d06d6bSBaptiste Daroussin 	size_t			  ssz, nsz, tsz;
7061d06d6bSBaptiste Daroussin 	unsigned int		  slot;
7161d06d6bSBaptiste Daroussin 	int			  ret;
7261d06d6bSBaptiste Daroussin 	uint32_t		  hv;
7361d06d6bSBaptiste Daroussin 
7461d06d6bSBaptiste Daroussin 	if (xr_hash == NULL)
7561d06d6bSBaptiste Daroussin 		return 0;
7661d06d6bSBaptiste Daroussin 
7761d06d6bSBaptiste Daroussin 	ssz = strlen(sec) + 1;
7861d06d6bSBaptiste Daroussin 	nsz = strlen(name) + 1;
7961d06d6bSBaptiste Daroussin 	tsz = ssz + nsz;
8061d06d6bSBaptiste Daroussin 	xr = mandoc_malloc(sizeof(*xr) + tsz);
8161d06d6bSBaptiste Daroussin 	xr->next = NULL;
8261d06d6bSBaptiste Daroussin 	xr->sec = xr->hashkey;
8361d06d6bSBaptiste Daroussin 	xr->name = xr->hashkey + ssz;
8461d06d6bSBaptiste Daroussin 	xr->line = line;
8561d06d6bSBaptiste Daroussin 	xr->pos = pos;
8661d06d6bSBaptiste Daroussin 	xr->count = 1;
8761d06d6bSBaptiste Daroussin 	memcpy(xr->sec, sec, ssz);
8861d06d6bSBaptiste Daroussin 	memcpy(xr->name, name, nsz);
8961d06d6bSBaptiste Daroussin 
9061d06d6bSBaptiste Daroussin 	pend = xr->hashkey + tsz;
9161d06d6bSBaptiste Daroussin 	hv = ohash_interval(xr->hashkey, &pend);
9261d06d6bSBaptiste Daroussin 	slot = ohash_lookup_memory(xr_hash, xr->hashkey, tsz, hv);
9361d06d6bSBaptiste Daroussin 	if ((oxr = ohash_find(xr_hash, slot)) == NULL) {
9461d06d6bSBaptiste Daroussin 		ohash_insert(xr_hash, slot, xr);
9561d06d6bSBaptiste Daroussin 		if (xr_first == NULL)
9661d06d6bSBaptiste Daroussin 			xr_first = xr;
9761d06d6bSBaptiste Daroussin 		else
9861d06d6bSBaptiste Daroussin 			xr_last->next = xr;
9961d06d6bSBaptiste Daroussin 		xr_last = xr;
10061d06d6bSBaptiste Daroussin 		return 0;
10161d06d6bSBaptiste Daroussin 	}
10261d06d6bSBaptiste Daroussin 
10361d06d6bSBaptiste Daroussin 	oxr->count++;
10461d06d6bSBaptiste Daroussin 	ret = (oxr->line == -1) ^ (xr->line == -1);
10561d06d6bSBaptiste Daroussin 	if (xr->line == -1)
10661d06d6bSBaptiste Daroussin 		oxr->line = -1;
10761d06d6bSBaptiste Daroussin 	free(xr);
10861d06d6bSBaptiste Daroussin 	return ret;
10961d06d6bSBaptiste Daroussin }
11061d06d6bSBaptiste Daroussin 
11161d06d6bSBaptiste Daroussin struct mandoc_xr *
mandoc_xr_get(void)11261d06d6bSBaptiste Daroussin mandoc_xr_get(void)
11361d06d6bSBaptiste Daroussin {
11461d06d6bSBaptiste Daroussin 	return xr_first;
11561d06d6bSBaptiste Daroussin }
11661d06d6bSBaptiste Daroussin 
11761d06d6bSBaptiste Daroussin void
mandoc_xr_free(void)11861d06d6bSBaptiste Daroussin mandoc_xr_free(void)
11961d06d6bSBaptiste Daroussin {
12061d06d6bSBaptiste Daroussin 	mandoc_xr_clear();
12161d06d6bSBaptiste Daroussin 	free(xr_hash);
12261d06d6bSBaptiste Daroussin 	xr_hash = NULL;
12361d06d6bSBaptiste Daroussin }
124