Blame clients/uil/UilSymNam.c

Packit b099d7
/* 
Packit b099d7
 * Motif
Packit b099d7
 *
Packit b099d7
 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are free software; you can
Packit b099d7
 * redistribute them and/or modify them under the terms of the GNU
Packit b099d7
 * Lesser General Public License as published by the Free Software
Packit b099d7
 * Foundation; either version 2 of the License, or (at your option)
Packit b099d7
 * any later version.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are distributed in the hope that
Packit b099d7
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
Packit b099d7
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Packit b099d7
 * PURPOSE. See the GNU Lesser General Public License for more
Packit b099d7
 * details.
Packit b099d7
 *
Packit b099d7
 * You should have received a copy of the GNU Lesser General Public
Packit b099d7
 * License along with these librararies and programs; if not, write
Packit b099d7
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
Packit b099d7
 * Floor, Boston, MA 02110-1301 USA
Packit b099d7
*/ 
Packit b099d7
/* 
Packit b099d7
 * HISTORY
Packit b099d7
*/ 
Packit b099d7
#ifdef REV_INFO
Packit b099d7
#ifndef lint
Packit b099d7
static char rcsid[] = "$TOG: UilSymNam.c /main/13 1997/09/08 11:12:50 cshi $"
Packit b099d7
#endif
Packit b099d7
#endif
Packit b099d7
Packit b099d7
#ifdef HAVE_CONFIG_H
Packit b099d7
#include <config.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
Packit b099d7
/*
Packit b099d7
*  (c) Copyright 1989, 1990, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */
Packit b099d7
Packit b099d7
/*
Packit b099d7
**++
Packit b099d7
**  FACILITY:
Packit b099d7
**
Packit b099d7
**      User Interface Language Compiler (UIL)
Packit b099d7
**
Packit b099d7
**  ABSTRACT:
Packit b099d7
**
Packit b099d7
**      This module inserts names into the name table.
Packit b099d7
**
Packit b099d7
**--
Packit b099d7
**/
Packit b099d7
Packit b099d7
Packit b099d7
/*
Packit b099d7
**
Packit b099d7
**  INCLUDE FILES
Packit b099d7
**
Packit b099d7
**/
Packit b099d7
Packit b099d7
#include "UilDefI.h"
Packit b099d7
Packit b099d7
/*
Packit b099d7
**
Packit b099d7
**  DEFINE and MACRO DEFINITIONS
Packit b099d7
**
Packit b099d7
**/
Packit b099d7
Packit b099d7
Packit b099d7
/*
Packit b099d7
**
Packit b099d7
**  EXTERNAL VARIABLE DECLARATIONS
Packit b099d7
**
Packit b099d7
**/
Packit b099d7
Packit b099d7
Packit b099d7
Packit b099d7
/*
Packit b099d7
**
Packit b099d7
**  GLOBAL VARIABLE DECLARATIONS
Packit b099d7
**
Packit b099d7
**/
Packit b099d7
Packit b099d7
Packit b099d7
Packit b099d7
/*
Packit b099d7
**
Packit b099d7
**  OWN VARIABLE DECLARATIONS
Packit b099d7
**
Packit b099d7
**/
Packit b099d7
Packit b099d7
Packit b099d7

Packit b099d7
/*
Packit b099d7
**++
Packit b099d7
**  FUNCTIONAL DESCRIPTION:
Packit b099d7
**
Packit b099d7
**  This routine searches for a name entry of the same name as its parameters.
Packit b099d7
**  If the entry is found, a pointer to that name node is 
Packit b099d7
**  returned as the value of the function.  If no entry is found, a NULL
Packit b099d7
**  pointer is returned.
Packit b099d7
**
Packit b099d7
**  See sym_insert_name for a description of the name lookup alorithm.
Packit b099d7
**
Packit b099d7
**  FORMAL PARAMETERS:
Packit b099d7
**
Packit b099d7
**      l_length	    length of the name not including the null
Packit b099d7
**	c_text		    pointer to a null terminated string for name
Packit b099d7
**
Packit b099d7
**  IMPLICIT INPUTS:
Packit b099d7
**
Packit b099d7
**      sym_az_hash_table   the hash table
Packit b099d7
**
Packit b099d7
**  IMPLICIT OUTPUTS:
Packit b099d7
**
Packit b099d7
**      sym_az_hash_table   may be updated with an additional name
Packit b099d7
**
Packit b099d7
**  FUNCTION VALUE:
Packit b099d7
**
Packit b099d7
**      a pointer to a name entry
Packit b099d7
**
Packit b099d7
**  SIDE EFFECTS:
Packit b099d7
**
Packit b099d7
**      none
Packit b099d7
**
Packit b099d7
**--
Packit b099d7
**/
Packit b099d7
Packit b099d7
sym_name_entry_type 
Packit b099d7
    *sym_find_name(l_length, c_text)
Packit b099d7
Packit b099d7
int	l_length;	/* length of name to find */
Packit b099d7
char	*c_text;	/* text of the name */
Packit b099d7
Packit b099d7
{
Packit b099d7
    sym_name_entry_type	*az_current_name;
Packit b099d7
    int			l_hash_code;
Packit b099d7
    int			l_compare_result;
Packit b099d7
Packit b099d7
    /* obtain the hash code of for the name */
Packit b099d7
Packit b099d7
    l_hash_code = hash_function( l_length, c_text );
Packit b099d7
Packit b099d7
    /*
Packit b099d7
    **  chain along hash chain looking for symbol - exit loop under 3 condition
Packit b099d7
    **        1) come to the end of the chain: name not found
Packit b099d7
    **        2) find symbol: return this symbol
Packit b099d7
    **        3) find node > symbol: name not found
Packit b099d7
    */
Packit b099d7
Packit b099d7
    for (az_current_name = sym_az_hash_table[ l_hash_code ];
Packit b099d7
	 az_current_name != NULL;
Packit b099d7
	 az_current_name = az_current_name->az_next_name_entry)
Packit b099d7
    {
Packit b099d7
	l_compare_result = _compare(c_text, az_current_name->c_text);
Packit b099d7
Packit b099d7
	if (l_compare_result == 0)	/* c_text = current name */
Packit b099d7
	{
Packit b099d7
	    /* found the name we are looking for */
Packit b099d7
Packit b099d7
	    return az_current_name;
Packit b099d7
	}
Packit b099d7
Packit b099d7
	if (l_compare_result > 0)	/* c_text > current name */
Packit b099d7
	{
Packit b099d7
	    /* return NULL - name should be before this spot in list */
Packit b099d7
Packit b099d7
	    return NULL;
Packit b099d7
	}
Packit b099d7
Packit b099d7
    }
Packit b099d7
Packit b099d7
    /* came to end of the list without finding the name */
Packit b099d7
Packit b099d7
    return NULL;
Packit b099d7
}
Packit b099d7
Packit b099d7

Packit b099d7
/*
Packit b099d7
**++
Packit b099d7
**  FUNCTIONAL DESCRIPTION:
Packit b099d7
**
Packit b099d7
**  This routine searches for a name entry of the same name as its parameters.
Packit b099d7
**  If the entry is found, a pointer to that name node is 
Packit b099d7
**  returned as the value of the function.  If no entry is found, one is 
Packit b099d7
**  inserted.  In this case the value of the function is a pointer to
Packit b099d7
**  the name entry created.
Packit b099d7
**
Packit b099d7
**  Name entries are linked off of a hash table.  Those
Packit b099d7
**  entries that have the same hash code, are sorted according to the
Packit b099d7
**  collating sequence.  Thus the algorithm involves hashing the symbol and
Packit b099d7
**  then following the chain for that hash code until one of the following
Packit b099d7
**  conditions is met.  1) the identifier is found, then return a pointer
Packit b099d7
**  to that name entry.  2) come to the end of the chain or a name
Packit b099d7
**  entry that comes later in the collating sequence than the symbol being
Packit b099d7
**  searched for.  In this case the name is inserted just prior to this
Packit b099d7
**  point in the chain.
Packit b099d7
**
Packit b099d7
**  FORMAL PARAMETERS:
Packit b099d7
**
Packit b099d7
**      l_length	    length of the name not including the null
Packit b099d7
**	c_text		    pointer to a null terminated string for name
Packit b099d7
**
Packit b099d7
**  IMPLICIT INPUTS:
Packit b099d7
**
Packit b099d7
**      sym_az_hash_table   the hash table
Packit b099d7
**
Packit b099d7
**  IMPLICIT OUTPUTS:
Packit b099d7
**
Packit b099d7
**      sym_az_hash_table   may be updated with an additional name
Packit b099d7
**
Packit b099d7
**  FUNCTION VALUE:
Packit b099d7
**
Packit b099d7
**      a pointer to a name entry
Packit b099d7
**
Packit b099d7
**  SIDE EFFECTS:
Packit b099d7
**
Packit b099d7
**      may create a name entry and update the hash table
Packit b099d7
**
Packit b099d7
**--
Packit b099d7
**/
Packit b099d7
Packit b099d7
sym_name_entry_type *sym_insert_name(l_length, c_text)
Packit b099d7
Packit b099d7
int	l_length;	/* length of name to insert */
Packit b099d7
char	*c_text;	/* text of the name */
Packit b099d7
Packit b099d7
{
Packit b099d7
    sym_name_entry_type	*az_previous_name;
Packit b099d7
    sym_name_entry_type	*az_current_name;
Packit b099d7
    sym_name_entry_type	*az_new_name;
Packit b099d7
    int			l_hash_code;
Packit b099d7
    int			l_compare_result;
Packit b099d7
Packit b099d7
    /*
Packit b099d7
    **  algorithm keeps 2 pointers, one for the previous name and one
Packit b099d7
    **  for the current name.  This permits easy insertion of a new name 
Packit b099d7
    */
Packit b099d7
Packit b099d7
Packit b099d7
    /* obtain the hash code of for the name */
Packit b099d7
Packit b099d7
    l_hash_code = hash_function( l_length, c_text );
Packit b099d7
Packit b099d7
    /*
Packit b099d7
    **  chain along hash chain looking for symbol - exit loop under 3 condition
Packit b099d7
    **        1) come to the end of the chain: insert new node on end
Packit b099d7
    **        2) find symbol: return this symbol
Packit b099d7
    **        3) find node > symbol: insert new node prior to current node
Packit b099d7
    */
Packit b099d7
Packit b099d7
    for (az_current_name = sym_az_hash_table[ l_hash_code ],
Packit b099d7
	 az_previous_name = NULL;
Packit b099d7
Packit b099d7
	 az_current_name != NULL;
Packit b099d7
Packit b099d7
	 az_previous_name = az_current_name,
Packit b099d7
	 az_current_name = az_current_name->az_next_name_entry)
Packit b099d7
    {
Packit b099d7
	l_compare_result = _compare(c_text, az_current_name->c_text);
Packit b099d7
Packit b099d7
	if (l_compare_result == 0)	/* c_text = current name */
Packit b099d7
	{
Packit b099d7
	    /* found the name we are looking for */
Packit b099d7
Packit b099d7
	    return az_current_name;
Packit b099d7
	}
Packit b099d7
Packit b099d7
	if (l_compare_result > 0)	/* c_text > current name */
Packit b099d7
	{
Packit b099d7
	    /* exit the loop to insert just prior to current name */
Packit b099d7
Packit b099d7
	    goto insert_name;
Packit b099d7
	}
Packit b099d7
Packit b099d7
    }
Packit b099d7
Packit b099d7
insert_name:
Packit b099d7
Packit b099d7
    /*
Packit b099d7
    **	name is not in the table so it must be inserted between the
Packit b099d7
    **  az_previous_name and az_current_name entries.
Packit b099d7
    */
Packit b099d7
Packit b099d7
    /* allocate and initialize the name entry */
Packit b099d7
Packit b099d7
    az_new_name = (sym_name_entry_type *)
Packit b099d7
	sem_allocate_node (sym_k_name_entry, 
Packit b099d7
			   sym_k_name_entry_size + l_length + 1);
Packit b099d7
Packit b099d7
    az_new_name->header.b_type = l_length;	/* b_type holds length */
Packit b099d7
    az_new_name->az_object = NULL;
Packit b099d7
    az_new_name->az_cycle_id = 0;
Packit b099d7
Packit b099d7
    _move( az_new_name->c_text, c_text, l_length+1 );
Packit b099d7
Packit b099d7
    /*
Packit b099d7
    **  link the name entry into the hash table
Packit b099d7
    */
Packit b099d7
Packit b099d7
    az_new_name->az_next_name_entry = az_current_name;
Packit b099d7
Packit b099d7
    if (az_previous_name == NULL)
Packit b099d7
	sym_az_hash_table[ l_hash_code ] = az_new_name;
Packit b099d7
    else
Packit b099d7
	az_previous_name->az_next_name_entry =
Packit b099d7
			(sym_name_entry_type *) az_new_name;
Packit b099d7
Packit b099d7
    return az_new_name;
Packit b099d7
}
Packit b099d7
Packit b099d7

Packit b099d7
/*
Packit b099d7
**++
Packit b099d7
**  FUNCTIONAL DESCRIPTION:
Packit b099d7
**
Packit b099d7
**      This procedure is a hashing function.  It takes a length and a
Packit b099d7
**	pointer to a value.  Using this value as a string, the function
Packit b099d7
**	returns an integer in the range of 0 to sym_k_hash_table_limit-1.
Packit b099d7
**
Packit b099d7
**  FORMAL PARAMETERS:
Packit b099d7
**
Packit b099d7
**      l_length	    length of the value in bytes not including null
Packit b099d7
**	c_value		    a null terminated string 
Packit b099d7
**
Packit b099d7
**  IMPLICIT INPUTS:
Packit b099d7
**
Packit b099d7
**      sym_k_hash_table_limit
Packit b099d7
**
Packit b099d7
**  IMPLICIT OUTPUTS:
Packit b099d7
**
Packit b099d7
**      none
Packit b099d7
**
Packit b099d7
**  FUNCTION VALUE:
Packit b099d7
**
Packit b099d7
**      integer (the hash code) in range 0 to sym_k_hash_table_limit-1
Packit b099d7
**
Packit b099d7
**  SIDE EFFECTS:
Packit b099d7
**
Packit b099d7
**      none
Packit b099d7
**
Packit b099d7
**--
Packit b099d7
**/
Packit b099d7
Packit b099d7
int	hash_function(l_length, c_value)
Packit b099d7
Packit b099d7
int	l_length;
Packit b099d7
char	*c_value;
Packit b099d7
{
Packit b099d7
#ifdef WORD64
Packit b099d7
#define _shift 3
Packit b099d7
    static unsigned int XmConst    mask[ 8 ] =
Packit b099d7
                { 0x00000000000000FF, 0x000000000000FFFF,
Packit b099d7
                  0x0000000000FFFFFF, 0x00000000FFFFFFFF,
Packit b099d7
                  0x00000000FFFFFFFF, 0x0000FFFFFFFFFFFF,
Packit b099d7
                  0x00FFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, };
Packit b099d7
#elif defined (LONG64)
Packit b099d7
    #define _shift 3
Packit b099d7
    static long XmConst    mask[ 8 ] =
Packit b099d7
                { 0x00000000000000FF, 0x000000000000FFFF,
Packit b099d7
                  0x0000000000FFFFFF, 0x00000000FFFFFFFF,
Packit b099d7
                  0x00000000FFFFFFFF, 0x0000FFFFFFFFFFFF,
Packit b099d7
                  0x00FFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, };
Packit b099d7
#else
Packit b099d7
#define _shift 2
Packit b099d7
    static unsigned int XmConst	mask[ 4 ] = 
Packit b099d7
		{ 0x000000FF, 0x0000FFFF, 0x00FFFFFF, 0xFFFFFFFF };
Packit b099d7
#endif
Packit b099d7
Packit b099d7
#ifdef LONG64
Packit b099d7
    long                l_hash_code;
Packit b099d7
    long                al_value[20];
Packit b099d7
#else
Packit b099d7
    int                 l_hash_code;
Packit b099d7
    int                 al_value[20];
Packit b099d7
#endif
Packit b099d7
    int	 	   	l_limit;
Packit b099d7
    int	  	  	l_extra;
Packit b099d7
    int	   	 	i;
Packit b099d7
Packit b099d7
    l_limit = (l_length-1) >> _shift;	/* divide by wordsize */
Packit b099d7
    l_extra = (l_length-1) & _slm;	/* remainder from divide by wordsize */
Packit b099d7
Packit b099d7
#ifdef LONG64
Packit b099d7
    bzero((char *)al_value, sizeof(long) * 20);
Packit b099d7
#else
Packit b099d7
    bzero((char *)al_value, sizeof(int) * 20);
Packit b099d7
#endif
Packit b099d7
    strncpy((char *)al_value, c_value, l_length);
Packit b099d7
    l_hash_code = 0;
Packit b099d7
Packit b099d7
    for (i = 0; i < l_limit; i++)
Packit b099d7
    {
Packit b099d7
	l_hash_code = l_hash_code ^ al_value[ i ];
Packit b099d7
    }
Packit b099d7
Packit b099d7
    l_hash_code = l_hash_code ^ (al_value[ i ] & mask[ l_extra ]);
Packit b099d7
Packit b099d7
    return (int)(l_hash_code % sym_k_hash_table_limit);
Packit b099d7
}
Packit b099d7
Packit b099d7

Packit b099d7
#if debug_version
Packit b099d7
Packit b099d7
/*
Packit b099d7
**++
Packit b099d7
**  FUNCTIONAL DESCRIPTION:
Packit b099d7
**
Packit b099d7
**      This debugging routine will dump out the name entries linked
Packit b099d7
**	from the hash table.
Packit b099d7
**
Packit b099d7
**  FORMAL PARAMETERS:
Packit b099d7
**
Packit b099d7
**      none
Packit b099d7
**
Packit b099d7
**  IMPLICIT INPUTS:
Packit b099d7
**
Packit b099d7
**      sym_az_hash_table
Packit b099d7
**
Packit b099d7
**  IMPLICIT OUTPUTS:
Packit b099d7
**
Packit b099d7
**      none
Packit b099d7
**
Packit b099d7
**  FUNCTION VALUE:
Packit b099d7
**
Packit b099d7
**      void
Packit b099d7
**
Packit b099d7
**  SIDE EFFECTS:
Packit b099d7
**
Packit b099d7
**      prints out the hash table
Packit b099d7
**
Packit b099d7
**--
Packit b099d7
**/
Packit b099d7
Packit b099d7
void	sym_dump_hash_table()
Packit b099d7
{
Packit b099d7
    int		i;
Packit b099d7
    int		total_count;
Packit b099d7
    int		max_length;
Packit b099d7
    int		empty_count;
Packit b099d7
Packit b099d7
    total_count = 0;
Packit b099d7
    empty_count = 0;
Packit b099d7
    max_length = 0;
Packit b099d7
	
Packit b099d7
    for (i=0;  i
Packit b099d7
    {
Packit b099d7
	int		    bucket_count;
Packit b099d7
	sym_name_entry_type  *az_name;
Packit b099d7
Packit b099d7
	bucket_count = 0;
Packit b099d7
Packit b099d7
	for (az_name = sym_az_hash_table[ i ];  
Packit b099d7
	     az_name != NULL;  
Packit b099d7
	     az_name = az_name->az_next_name_entry)
Packit b099d7
	{
Packit b099d7
	    bucket_count++;
Packit b099d7
Packit b099d7
	    _debug_output("\t %s \n", az_name->c_text);
Packit b099d7
	}
Packit b099d7
Packit b099d7
	total_count += bucket_count;
Packit b099d7
	if (bucket_count == 0)
Packit b099d7
	    empty_count++;
Packit b099d7
	max_length = ( max_length > bucket_count )? max_length : bucket_count;
Packit b099d7
Packit b099d7
	_debug_output("bucket: %d length: %d\n", i, bucket_count);
Packit b099d7
    }
Packit b099d7
Packit b099d7
    _debug_output("name count: %d \n empty count: %d \n max length: %d",
Packit b099d7
		   total_count, empty_count, max_length );
Packit b099d7
}
Packit b099d7
#endif