2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
26 * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
27 * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for
28 * the full copyright text.
35 static char rcsid[] = "$TOG: UilSymNam.c /main/13 1997/09/08 11:12:50 cshi $"
40 * (c) Copyright 1989, 1990, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */
46 ** User Interface Language Compiler (UIL)
50 ** This module inserts names into the name table.
66 ** DEFINE and MACRO DEFINITIONS
73 ** EXTERNAL VARIABLE DECLARATIONS
81 ** GLOBAL VARIABLE DECLARATIONS
89 ** OWN VARIABLE DECLARATIONS
97 ** FUNCTIONAL DESCRIPTION:
99 ** This routine searches for a name entry of the same name as its parameters.
100 ** If the entry is found, a pointer to that name node is
101 ** returned as the value of the function. If no entry is found, a NULL
102 ** pointer is returned.
104 ** See sym_insert_name for a description of the name lookup alorithm.
106 ** FORMAL PARAMETERS:
108 ** l_length length of the name not including the null
109 ** c_text pointer to a null terminated string for name
113 ** sym_az_hash_table the hash table
117 ** sym_az_hash_table may be updated with an additional name
121 ** a pointer to a name entry
131 *sym_find_name(l_length, c_text)
133 int l_length; /* length of name to find */
134 char *c_text; /* text of the name */
137 sym_name_entry_type *az_current_name;
139 int l_compare_result;
141 /* obtain the hash code of for the name */
143 l_hash_code = hash_function( l_length, c_text );
146 ** chain along hash chain looking for symbol - exit loop under 3 condition
147 ** 1) come to the end of the chain: name not found
148 ** 2) find symbol: return this symbol
149 ** 3) find node > symbol: name not found
152 for (az_current_name = sym_az_hash_table[ l_hash_code ];
153 az_current_name != NULL;
154 az_current_name = az_current_name->az_next_name_entry)
156 l_compare_result = _compare(c_text, az_current_name->c_text);
158 if (l_compare_result == 0) /* c_text = current name */
160 /* found the name we are looking for */
162 return az_current_name;
165 if (l_compare_result > 0) /* c_text > current name */
167 /* return NULL - name should be before this spot in list */
174 /* came to end of the list without finding the name */
182 ** FUNCTIONAL DESCRIPTION:
184 ** This routine searches for a name entry of the same name as its parameters.
185 ** If the entry is found, a pointer to that name node is
186 ** returned as the value of the function. If no entry is found, one is
187 ** inserted. In this case the value of the function is a pointer to
188 ** the name entry created.
190 ** Name entries are linked off of a hash table. Those
191 ** entries that have the same hash code, are sorted according to the
192 ** collating sequence. Thus the algorithm involves hashing the symbol and
193 ** then following the chain for that hash code until one of the following
194 ** conditions is met. 1) the identifier is found, then return a pointer
195 ** to that name entry. 2) come to the end of the chain or a name
196 ** entry that comes later in the collating sequence than the symbol being
197 ** searched for. In this case the name is inserted just prior to this
198 ** point in the chain.
200 ** FORMAL PARAMETERS:
202 ** l_length length of the name not including the null
203 ** c_text pointer to a null terminated string for name
207 ** sym_az_hash_table the hash table
211 ** sym_az_hash_table may be updated with an additional name
215 ** a pointer to a name entry
219 ** may create a name entry and update the hash table
224 sym_name_entry_type *sym_insert_name(l_length, c_text)
226 int l_length; /* length of name to insert */
227 char *c_text; /* text of the name */
230 sym_name_entry_type *az_previous_name;
231 sym_name_entry_type *az_current_name;
232 sym_name_entry_type *az_new_name;
234 int l_compare_result;
237 ** algorithm keeps 2 pointers, one for the previous name and one
238 ** for the current name. This permits easy insertion of a new name
242 /* obtain the hash code of for the name */
244 l_hash_code = hash_function( l_length, c_text );
247 ** chain along hash chain looking for symbol - exit loop under 3 condition
248 ** 1) come to the end of the chain: insert new node on end
249 ** 2) find symbol: return this symbol
250 ** 3) find node > symbol: insert new node prior to current node
253 for (az_current_name = sym_az_hash_table[ l_hash_code ],
254 az_previous_name = NULL;
256 az_current_name != NULL;
258 az_previous_name = az_current_name,
259 az_current_name = az_current_name->az_next_name_entry)
261 l_compare_result = _compare(c_text, az_current_name->c_text);
263 if (l_compare_result == 0) /* c_text = current name */
265 /* found the name we are looking for */
267 return az_current_name;
270 if (l_compare_result > 0) /* c_text > current name */
272 /* exit the loop to insert just prior to current name */
282 ** name is not in the table so it must be inserted between the
283 ** az_previous_name and az_current_name entries.
286 /* allocate and initialize the name entry */
288 az_new_name = (sym_name_entry_type *)
289 sem_allocate_node (sym_k_name_entry,
290 sym_k_name_entry_size + l_length + 1);
292 az_new_name->header.b_type = l_length; /* b_type holds length */
293 az_new_name->az_object = NULL;
294 az_new_name->az_cycle_id = 0;
296 _move( az_new_name->c_text, c_text, l_length+1 );
299 ** link the name entry into the hash table
302 az_new_name->az_next_name_entry = az_current_name;
304 if (az_previous_name == NULL)
305 sym_az_hash_table[ l_hash_code ] = az_new_name;
307 az_previous_name->az_next_name_entry =
308 (sym_name_entry_type *) az_new_name;
316 ** FUNCTIONAL DESCRIPTION:
318 ** This procedure is a hashing function. It takes a length and a
319 ** pointer to a value. Using this value as a string, the function
320 ** returns an integer in the range of 0 to sym_k_hash_table_limit-1.
322 ** FORMAL PARAMETERS:
324 ** l_length length of the value in bytes not including null
325 ** c_value a null terminated string
329 ** sym_k_hash_table_limit
337 ** integer (the hash code) in range 0 to sym_k_hash_table_limit-1
346 int hash_function(l_length, c_value)
353 static unsigned int XmConst mask[ 8 ] =
354 { 0x00000000000000FF, 0x000000000000FFFF,
355 0x0000000000FFFFFF, 0x00000000FFFFFFFF,
356 0x00000000FFFFFFFF, 0x0000FFFFFFFFFFFF,
357 0x00FFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, };
358 #elif defined (LONG64)
360 static long XmConst mask[ 8 ] =
361 { 0x00000000000000FF, 0x000000000000FFFF,
362 0x0000000000FFFFFF, 0x00000000FFFFFFFF,
363 0x00000000FFFFFFFF, 0x0000FFFFFFFFFFFF,
364 0x00FFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, };
367 static unsigned int XmConst mask[ 4 ] =
368 { 0x000000FF, 0x0000FFFF, 0x00FFFFFF, 0xFFFFFFFF };
382 l_limit = (l_length-1) >> _shift; /* divide by wordsize */
383 l_extra = (l_length-1) & _slm; /* remainder from divide by wordsize */
386 bzero((char *)al_value, sizeof(long) * 20);
388 bzero((char *)al_value, sizeof(int) * 20);
390 strncpy((char *)al_value, c_value, l_length);
393 for (i = 0; i < l_limit; i++)
395 l_hash_code = l_hash_code ^ al_value[ i ];
398 l_hash_code = l_hash_code ^ (al_value[ i ] & mask[ l_extra ]);
400 return (int)(l_hash_code % sym_k_hash_table_limit);
408 ** FUNCTIONAL DESCRIPTION:
410 ** This debugging routine will dump out the name entries linked
411 ** from the hash table.
413 ** FORMAL PARAMETERS:
431 ** prints out the hash table
436 void sym_dump_hash_table()
447 for (i=0; i<sym_k_hash_table_limit; i++)
450 sym_name_entry_type *az_name;
454 for (az_name = sym_az_hash_table[ i ];
456 az_name = az_name->az_next_name_entry)
460 _debug_output("\t %s \n", az_name->c_text);
463 total_count += bucket_count;
464 if (bucket_count == 0)
466 max_length = ( max_length > bucket_count )? max_length : bucket_count;
468 _debug_output("bucket: %d length: %d\n", i, bucket_count);
471 _debug_output("name count: %d \n empty count: %d \n max length: %d",
472 total_count, empty_count, max_length );