xref: /openbsd-src/usr.bin/mandoc/mandoc_xr.c (revision bff2a0c301a2f68ac08618b63a82f0a27dcaf3f1)
1*bff2a0c3Sschwarze /*	$OpenBSD: mandoc_xr.c,v 1.3 2017/07/02 21:17:12 schwarze Exp $ */
219b6bef7Sschwarze /*
319b6bef7Sschwarze  * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
419b6bef7Sschwarze  *
519b6bef7Sschwarze  * Permission to use, copy, modify, and distribute this software for any
619b6bef7Sschwarze  * purpose with or without fee is hereby granted, provided that the above
719b6bef7Sschwarze  * copyright notice and this permission notice appear in all copies.
819b6bef7Sschwarze  *
919b6bef7Sschwarze  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1019b6bef7Sschwarze  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1119b6bef7Sschwarze  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1219b6bef7Sschwarze  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1319b6bef7Sschwarze  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1419b6bef7Sschwarze  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1519b6bef7Sschwarze  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1619b6bef7Sschwarze  */
1719b6bef7Sschwarze #include <sys/types.h>
1819b6bef7Sschwarze 
1919b6bef7Sschwarze #include <assert.h>
2019b6bef7Sschwarze #include <stddef.h>
2119b6bef7Sschwarze #include <stdint.h>
2219b6bef7Sschwarze #include <stdlib.h>
2319b6bef7Sschwarze #include <string.h>
2419b6bef7Sschwarze 
2519b6bef7Sschwarze #include "mandoc_aux.h"
2619b6bef7Sschwarze #include "mandoc_ohash.h"
2719b6bef7Sschwarze #include "mandoc_xr.h"
2819b6bef7Sschwarze 
2919b6bef7Sschwarze static struct ohash	 *xr_hash = NULL;
3019b6bef7Sschwarze static struct mandoc_xr	 *xr_first = NULL;
3119b6bef7Sschwarze static struct mandoc_xr	 *xr_last = NULL;
3219b6bef7Sschwarze 
3319b6bef7Sschwarze static void		  mandoc_xr_clear(void);
3419b6bef7Sschwarze 
3519b6bef7Sschwarze 
3619b6bef7Sschwarze static void
mandoc_xr_clear(void)3719b6bef7Sschwarze mandoc_xr_clear(void)
3819b6bef7Sschwarze {
3919b6bef7Sschwarze 	struct mandoc_xr	*xr;
4019b6bef7Sschwarze 	unsigned int		 slot;
4119b6bef7Sschwarze 
4219b6bef7Sschwarze 	if (xr_hash == NULL)
4319b6bef7Sschwarze 		return;
4419b6bef7Sschwarze 	for (xr = ohash_first(xr_hash, &slot); xr != NULL;
4519b6bef7Sschwarze 	     xr = ohash_next(xr_hash, &slot))
4619b6bef7Sschwarze 		free(xr);
4719b6bef7Sschwarze 	ohash_delete(xr_hash);
4819b6bef7Sschwarze }
4919b6bef7Sschwarze 
5019b6bef7Sschwarze void
mandoc_xr_reset(void)5119b6bef7Sschwarze mandoc_xr_reset(void)
5219b6bef7Sschwarze {
5319b6bef7Sschwarze 	if (xr_hash == NULL)
5419b6bef7Sschwarze 		xr_hash = mandoc_malloc(sizeof(*xr_hash));
5519b6bef7Sschwarze 	else
5619b6bef7Sschwarze 		mandoc_xr_clear();
5719b6bef7Sschwarze 	mandoc_ohash_init(xr_hash, 5,
5819b6bef7Sschwarze 	    offsetof(struct mandoc_xr, hashkey));
5919b6bef7Sschwarze 	xr_first = xr_last = NULL;
6019b6bef7Sschwarze }
6119b6bef7Sschwarze 
6252d11c96Sschwarze int
mandoc_xr_add(const char * sec,const char * name,int line,int pos)6319b6bef7Sschwarze mandoc_xr_add(const char *sec, const char *name, int line, int pos)
6419b6bef7Sschwarze {
6552d11c96Sschwarze 	struct mandoc_xr	 *xr, *oxr;
6619b6bef7Sschwarze 	const char		 *pend;
6719b6bef7Sschwarze 	size_t			  ssz, nsz, tsz;
6819b6bef7Sschwarze 	unsigned int		  slot;
6952d11c96Sschwarze 	int			  ret;
7019b6bef7Sschwarze 	uint32_t		  hv;
7119b6bef7Sschwarze 
7219b6bef7Sschwarze 	if (xr_hash == NULL)
7352d11c96Sschwarze 		return 0;
7419b6bef7Sschwarze 
7519b6bef7Sschwarze 	ssz = strlen(sec) + 1;
7619b6bef7Sschwarze 	nsz = strlen(name) + 1;
7719b6bef7Sschwarze 	tsz = ssz + nsz;
7819b6bef7Sschwarze 	xr = mandoc_malloc(sizeof(*xr) + tsz);
7919b6bef7Sschwarze 	xr->next = NULL;
8019b6bef7Sschwarze 	xr->sec = xr->hashkey;
8119b6bef7Sschwarze 	xr->name = xr->hashkey + ssz;
8219b6bef7Sschwarze 	xr->line = line;
8319b6bef7Sschwarze 	xr->pos = pos;
84*bff2a0c3Sschwarze 	xr->count = 1;
8519b6bef7Sschwarze 	memcpy(xr->sec, sec, ssz);
8619b6bef7Sschwarze 	memcpy(xr->name, name, nsz);
8719b6bef7Sschwarze 
8819b6bef7Sschwarze 	pend = xr->hashkey + tsz;
8919b6bef7Sschwarze 	hv = ohash_interval(xr->hashkey, &pend);
9019b6bef7Sschwarze 	slot = ohash_lookup_memory(xr_hash, xr->hashkey, tsz, hv);
9152d11c96Sschwarze 	if ((oxr = ohash_find(xr_hash, slot)) == NULL) {
9219b6bef7Sschwarze 		ohash_insert(xr_hash, slot, xr);
9319b6bef7Sschwarze 		if (xr_first == NULL)
9419b6bef7Sschwarze 			xr_first = xr;
9519b6bef7Sschwarze 		else
9619b6bef7Sschwarze 			xr_last->next = xr;
9719b6bef7Sschwarze 		xr_last = xr;
9852d11c96Sschwarze 		return 0;
9952d11c96Sschwarze 	}
10052d11c96Sschwarze 
101*bff2a0c3Sschwarze 	oxr->count++;
10252d11c96Sschwarze 	ret = (oxr->line == -1) ^ (xr->line == -1);
10352d11c96Sschwarze 	if (xr->line == -1)
10452d11c96Sschwarze 		oxr->line = -1;
10519b6bef7Sschwarze 	free(xr);
10652d11c96Sschwarze 	return ret;
10719b6bef7Sschwarze }
10819b6bef7Sschwarze 
10919b6bef7Sschwarze struct mandoc_xr *
mandoc_xr_get(void)11019b6bef7Sschwarze mandoc_xr_get(void)
11119b6bef7Sschwarze {
11219b6bef7Sschwarze 	return xr_first;
11319b6bef7Sschwarze }
11419b6bef7Sschwarze 
11519b6bef7Sschwarze void
mandoc_xr_free(void)11619b6bef7Sschwarze mandoc_xr_free(void)
11719b6bef7Sschwarze {
11819b6bef7Sschwarze 	mandoc_xr_clear();
11919b6bef7Sschwarze 	free(xr_hash);
12019b6bef7Sschwarze 	xr_hash = NULL;
12119b6bef7Sschwarze }
122