1241675Suqs/*	$Id: mdoc_hash.c,v 1.18 2011/07/24 18:15:14 kristaps Exp $ */
2241675Suqs/*
3241675Suqs * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
4241675Suqs *
5241675Suqs * Permission to use, copy, modify, and distribute this software for any
6241675Suqs * purpose with or without fee is hereby granted, provided that the above
7241675Suqs * copyright notice and this permission notice appear in all copies.
8241675Suqs *
9241675Suqs * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10241675Suqs * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11241675Suqs * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12241675Suqs * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13241675Suqs * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14241675Suqs * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15241675Suqs * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16241675Suqs */
17241675Suqs#ifdef HAVE_CONFIG_H
18241675Suqs#include "config.h"
19241675Suqs#endif
20241675Suqs
21241675Suqs#include <sys/types.h>
22241675Suqs
23241675Suqs#include <assert.h>
24241675Suqs#include <ctype.h>
25241675Suqs#include <limits.h>
26241675Suqs#include <stdlib.h>
27241675Suqs#include <stdio.h>
28241675Suqs#include <string.h>
29241675Suqs
30241675Suqs#include "mdoc.h"
31241675Suqs#include "mandoc.h"
32241675Suqs#include "libmdoc.h"
33241675Suqs
34241675Suqsstatic	unsigned char	 table[27 * 12];
35241675Suqs
36241675Suqs/*
37241675Suqs * XXX - this hash has global scope, so if intended for use as a library
38241675Suqs * with multiple callers, it will need re-invocation protection.
39241675Suqs */
40241675Suqsvoid
41241675Suqsmdoc_hash_init(void)
42241675Suqs{
43241675Suqs	int		 i, j, major;
44241675Suqs	const char	*p;
45241675Suqs
46241675Suqs	memset(table, UCHAR_MAX, sizeof(table));
47241675Suqs
48241675Suqs	for (i = 0; i < (int)MDOC_MAX; i++) {
49241675Suqs		p = mdoc_macronames[i];
50241675Suqs
51241675Suqs		if (isalpha((unsigned char)p[1]))
52241675Suqs			major = 12 * (tolower((unsigned char)p[1]) - 97);
53241675Suqs		else
54241675Suqs			major = 12 * 26;
55241675Suqs
56241675Suqs		for (j = 0; j < 12; j++)
57241675Suqs			if (UCHAR_MAX == table[major + j]) {
58241675Suqs				table[major + j] = (unsigned char)i;
59241675Suqs				break;
60241675Suqs			}
61241675Suqs
62241675Suqs		assert(j < 12);
63241675Suqs	}
64241675Suqs}
65241675Suqs
66241675Suqsenum mdoct
67241675Suqsmdoc_hash_find(const char *p)
68241675Suqs{
69241675Suqs	int		  major, i, j;
70241675Suqs
71241675Suqs	if (0 == p[0])
72241675Suqs		return(MDOC_MAX);
73241675Suqs	if ( ! isalpha((unsigned char)p[0]) && '%' != p[0])
74241675Suqs		return(MDOC_MAX);
75241675Suqs
76241675Suqs	if (isalpha((unsigned char)p[1]))
77241675Suqs		major = 12 * (tolower((unsigned char)p[1]) - 97);
78241675Suqs	else if ('1' == p[1])
79241675Suqs		major = 12 * 26;
80241675Suqs	else
81241675Suqs		return(MDOC_MAX);
82241675Suqs
83241675Suqs	if (p[2] && p[3])
84241675Suqs		return(MDOC_MAX);
85241675Suqs
86241675Suqs	for (j = 0; j < 12; j++) {
87241675Suqs		if (UCHAR_MAX == (i = table[major + j]))
88241675Suqs			break;
89241675Suqs		if (0 == strcmp(p, mdoc_macronames[i]))
90241675Suqs			return((enum mdoct)i);
91241675Suqs	}
92241675Suqs
93241675Suqs	return(MDOC_MAX);
94241675Suqs}
95