summaryrefslogblamecommitdiffstats
path: root/mdoc_hash.c
blob: dea68f283fb8c84d860b6ba85c0c69c6c665f194 (plain) (tree)
1
2
3
4
5
6
7
8
               
  
                                                               

                                                                        

                                                                         
  






                                                                           


                   



                   
                    
 


























                                                                 
 
    
                          





                   
 
      
                     
 
                                               

                               
                                                                
                          
                             
 
                                        
                                              
                                                              
 
                                    

                                              
                                                              
 
                                    
 
                                          
 










                                                    
                                            






                             
                                                
 
                                                  

                               

                                   
 
                                  
                                 
                                  
                                 
 
                             

                                 


                                                    

                                 

                            
 
                                  
 


                                          




                                                                      
                                       








                                                                      
                                       


                                     
 

                                 


                                                              
                                          
                               
                             
 
                         

 
/*	$Id$ */
/*
 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "libmdoc.h"

#define	ADJUST_MAJOR(x) 					\
	do if (37 == (x))					\
		(x) = 0; 		/* %   -> 00 */		\
	else if (91 > (x)) 					\
		(x) -= 64; 		/* A-Z -> 01 - 26 */	\
	else 							\
		(x) -= 70;		/* a-z -> 27 - 52 */	\
	while (/*CONSTCOND*/0)

#define ADJUST_MINOR(y)						\
	do if (49 == (y))					\
		(y) = 0;		/* 1   -> 00 */		\
	else if (91 > (y))					\
		(y) -= 65;		/* A-Z -> 00 - 25 */	\
	else 							\
		(y) -= 97;		/* a-z -> 00 - 25 */	\
	while (/*CONSTCOND*/0)

#define INDEX(maj, min) 					\
	((maj) * 26 * 3) + ((min) * 3)

#define	SLOTCMP(slot, val)					\
	(mdoc_macronames[(slot)][0] == (val)[0] && 		\
	 mdoc_macronames[(slot)][1] == (val)[1] && 		\
	 (0 == (val)[2] || 					\
	  mdoc_macronames[(slot)][2] == (val)[2]))


void
mdoc_hash_free(void *htab)
{

	free(htab);
}



void *
mdoc_hash_alloc(void)
{
	int		  i, major, minor, ind;
	const void	**htab;

	htab = calloc(26 * 3 * 52, sizeof(struct mdoc_macro *));
	if (NULL == htab) 
		return(NULL);

	for (i = 0; i < MDOC_MAX; i++) {
		major = mdoc_macronames[i][0];
		assert(isalpha((u_char)major) || 37 == major);

		ADJUST_MAJOR(major);

		minor = mdoc_macronames[i][1];
		assert(isalpha((u_char)minor) || 49 == minor);

		ADJUST_MINOR(minor);

		ind = INDEX(major, minor);

		if (NULL == htab[ind]) {
			htab[ind] = &mdoc_macros[i];
			continue;
		}

		if (NULL == htab[++ind]) {
			htab[ind] = &mdoc_macros[i];
			continue;
		}

		assert(NULL == htab[++ind]);
		htab[ind] = &mdoc_macros[i];
	}

	return((void *)htab);
}


int
mdoc_hash_find(const void *arg, const char *tmp)
{
	int		  major, minor, ind, slot;
	const void	**htab;

	htab = /* LINTED */
		(const void **)arg;

	if (0 == (major = tmp[0]))
		return(MDOC_MAX);
	if (0 == (minor = tmp[1]))
		return(MDOC_MAX);

	if (tmp[2] && tmp[3])
		return(MDOC_MAX);

	if (37 != major && ! isalpha((u_char)major))
		return(MDOC_MAX);
	if (49 != minor && ! isalpha((u_char)minor))
		return(MDOC_MAX);

	ADJUST_MAJOR(major);
	ADJUST_MINOR(minor);

	ind = INDEX(major, minor);

	if (ind < 0 || ind >= 26 * 3 * 52)
		return(MDOC_MAX);

	if (htab[ind]) {
		slot = htab[ind] - /* LINTED */
			(void *)mdoc_macros;
		assert(0 == (size_t)slot % sizeof(struct mdoc_macro));
		slot /= sizeof(struct mdoc_macro);
		if (SLOTCMP(slot, tmp))
			return(slot);
		ind++;
	}

	if (htab[ind]) {
		slot = htab[ind] - /* LINTED */
			(void *)mdoc_macros;
		assert(0 == (size_t)slot % sizeof(struct mdoc_macro));
		slot /= sizeof(struct mdoc_macro);
		if (SLOTCMP(slot, tmp))
			return(slot);
		ind++;
	}

	if (NULL == htab[ind]) 
		return(MDOC_MAX);
	slot = htab[ind] - /* LINTED */
		(void *)mdoc_macros;
	assert(0 == (size_t)slot % sizeof(struct mdoc_macro));
	slot /= sizeof(struct mdoc_macro);
	if (SLOTCMP(slot, tmp))
		return(slot);

	return(MDOC_MAX);
}