1/*	$Id: mdoc_hash.c,v 1.26 2015/10/06 18:32:19 schwarze Exp $ */
2/*
3 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18#include "config.h"
19
20#include <sys/types.h>
21
22#include <assert.h>
23#include <ctype.h>
24#include <limits.h>
25#include <stdlib.h>
26#include <stdio.h>
27#include <string.h>
28
29#include "roff.h"
30#include "mdoc.h"
31#include "libmdoc.h"
32
33static	unsigned char	 table[27 * 12];
34
35
36void
37mdoc_hash_init(void)
38{
39	int		 i, j, major;
40	const char	*p;
41
42	if (*table != '\0')
43		return;
44
45	memset(table, UCHAR_MAX, sizeof(table));
46
47	for (i = 0; i < (int)MDOC_MAX; i++) {
48		p = mdoc_macronames[i];
49
50		if (isalpha((unsigned char)p[1]))
51			major = 12 * (tolower((unsigned char)p[1]) - 97);
52		else
53			major = 12 * 26;
54
55		for (j = 0; j < 12; j++)
56			if (UCHAR_MAX == table[major + j]) {
57				table[major + j] = (unsigned char)i;
58				break;
59			}
60
61		assert(j < 12);
62	}
63}
64
65int
66mdoc_hash_find(const char *p)
67{
68	int		  major, i, j;
69
70	if (0 == p[0])
71		return TOKEN_NONE;
72	if ( ! isalpha((unsigned char)p[0]) && '%' != p[0])
73		return TOKEN_NONE;
74
75	if (isalpha((unsigned char)p[1]))
76		major = 12 * (tolower((unsigned char)p[1]) - 97);
77	else if ('1' == p[1])
78		major = 12 * 26;
79	else
80		return TOKEN_NONE;
81
82	if (p[2] && p[3])
83		return TOKEN_NONE;
84
85	for (j = 0; j < 12; j++) {
86		if (UCHAR_MAX == (i = table[major + j]))
87			break;
88		if (0 == strcmp(p, mdoc_macronames[i]))
89			return i;
90	}
91
92	return TOKEN_NONE;
93}
94