1296781Sdes/* $Id: mandoc_xr.c,v 1.3 2017/07/02 21:18:29 schwarze Exp $ */ 2225825Sdes/* 3225825Sdes * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org> 4225825Sdes * 5225825Sdes * Permission to use, copy, modify, and distribute this software for any 6225825Sdes * purpose with or without fee is hereby granted, provided that the above 7225825Sdes * copyright notice and this permission notice appear in all copies. 8225825Sdes * 9225825Sdes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10225825Sdes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11225825Sdes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12225825Sdes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13225825Sdes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14225825Sdes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15225825Sdes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16225825Sdes */ 17225825Sdes#include <sys/types.h> 18225825Sdes 19225825Sdes#include <assert.h> 20225825Sdes#include <stddef.h> 21225825Sdes#include <stdint.h> 22225825Sdes#include <stdlib.h> 23225825Sdes#include <string.h> 24225825Sdes 25225825Sdes#include "mandoc_aux.h" 26240075Sdes#include "mandoc_ohash.h" 27225825Sdes#include "mandoc_xr.h" 28225825Sdes 29225825Sdesstatic struct ohash *xr_hash = NULL; 30225825Sdesstatic struct mandoc_xr *xr_first = NULL; 31225825Sdesstatic struct mandoc_xr *xr_last = NULL; 32225825Sdes 33240075Sdesstatic void mandoc_xr_clear(void); 34225825Sdes 35225825Sdes 36225825Sdesstatic void 37225825Sdesmandoc_xr_clear(void) 38225825Sdes{ 39295367Sdes struct mandoc_xr *xr; 40225825Sdes unsigned int slot; 41225825Sdes 42225825Sdes if (xr_hash == NULL) 43225825Sdes return; 44225825Sdes for (xr = ohash_first(xr_hash, &slot); xr != NULL; 45225825Sdes xr = ohash_next(xr_hash, &slot)) 46225825Sdes free(xr); 47225825Sdes ohash_delete(xr_hash); 48225825Sdes} 49225825Sdes 50225825Sdesvoid 51225825Sdesmandoc_xr_reset(void) 52225825Sdes{ 53296781Sdes if (xr_hash == NULL) 54296781Sdes xr_hash = mandoc_malloc(sizeof(*xr_hash)); 55296781Sdes else 56296781Sdes mandoc_xr_clear(); 57296781Sdes mandoc_ohash_init(xr_hash, 5, 58296781Sdes offsetof(struct mandoc_xr, hashkey)); 59296781Sdes xr_first = xr_last = NULL; 60295367Sdes} 61296781Sdes 62296781Sdesint 63296781Sdesmandoc_xr_add(const char *sec, const char *name, int line, int pos) 64295367Sdes{ 65295367Sdes struct mandoc_xr *xr, *oxr; 66295367Sdes const char *pend; 67295367Sdes size_t ssz, nsz, tsz; 68295367Sdes unsigned int slot; 69295367Sdes int ret; 70295367Sdes uint32_t hv; 71296781Sdes 72296781Sdes if (xr_hash == NULL) 73295367Sdes return 0; 74296781Sdes 75225825Sdes ssz = strlen(sec) + 1; 76225825Sdes nsz = strlen(name) + 1; 77225825Sdes tsz = ssz + nsz; 78240075Sdes xr = mandoc_malloc(sizeof(*xr) + tsz); 79295367Sdes xr->next = NULL; 80296781Sdes xr->sec = xr->hashkey; 81225825Sdes xr->name = xr->hashkey + ssz; 82296781Sdes xr->line = line; 83225825Sdes xr->pos = pos; 84296781Sdes xr->count = 1; 85264377Sdes memcpy(xr->sec, sec, ssz); 86296781Sdes memcpy(xr->name, name, nsz); 87296781Sdes 88296781Sdes pend = xr->hashkey + tsz; 89296781Sdes hv = ohash_interval(xr->hashkey, &pend); 90225825Sdes slot = ohash_lookup_memory(xr_hash, xr->hashkey, tsz, hv); 91225825Sdes if ((oxr = ohash_find(xr_hash, slot)) == NULL) { 92225825Sdes ohash_insert(xr_hash, slot, xr); 93225825Sdes if (xr_first == NULL) 94225825Sdes xr_first = xr; 95225825Sdes else 96240075Sdes xr_last->next = xr; 97225825Sdes xr_last = xr; 98225825Sdes return 0; 99225825Sdes } 100262566Sdes 101225825Sdes oxr->count++; 102225825Sdes ret = (oxr->line == -1) ^ (xr->line == -1); 103225825Sdes if (xr->line == -1) 104225825Sdes oxr->line = -1; 105225825Sdes free(xr); 106225825Sdes return ret; 107225825Sdes} 108240075Sdes 109225825Sdesstruct mandoc_xr * 110225825Sdesmandoc_xr_get(void) 111225825Sdes{ 112225825Sdes return xr_first; 113225825Sdes} 114225825Sdes 115225825Sdesvoid 116225825Sdesmandoc_xr_free(void) 117240075Sdes{ 118240075Sdes mandoc_xr_clear(); 119240075Sdes free(xr_hash); 120225825Sdes xr_hash = NULL; 121225825Sdes} 122225825Sdes