UilSymNam.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  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)
  10. * any later version.
  11. *
  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
  16. * details.
  17. *
  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
  22. */
  23. /*
  24. * @OSF_COPYRIGHT@
  25. * COPYRIGHT NOTICE
  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.
  29. */
  30. /*
  31. * HISTORY
  32. */
  33. #ifdef REV_INFO
  34. #ifndef lint
  35. static char rcsid[] = "$TOG: UilSymNam.c /main/13 1997/09/08 11:12:50 cshi $"
  36. #endif
  37. #endif
  38. /*
  39. * (c) Copyright 1989, 1990, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */
  40. /*
  41. **++
  42. ** FACILITY:
  43. **
  44. ** User Interface Language Compiler (UIL)
  45. **
  46. ** ABSTRACT:
  47. **
  48. ** This module inserts names into the name table.
  49. **
  50. **--
  51. **/
  52. /*
  53. **
  54. ** INCLUDE FILES
  55. **
  56. **/
  57. #include "UilDefI.h"
  58. /*
  59. **
  60. ** DEFINE and MACRO DEFINITIONS
  61. **
  62. **/
  63. /*
  64. **
  65. ** EXTERNAL VARIABLE DECLARATIONS
  66. **
  67. **/
  68. /*
  69. **
  70. ** GLOBAL VARIABLE DECLARATIONS
  71. **
  72. **/
  73. /*
  74. **
  75. ** OWN VARIABLE DECLARATIONS
  76. **
  77. **/
  78. /*
  79. **++
  80. ** FUNCTIONAL DESCRIPTION:
  81. **
  82. ** This routine searches for a name entry of the same name as its parameters.
  83. ** If the entry is found, a pointer to that name node is
  84. ** returned as the value of the function. If no entry is found, a NULL
  85. ** pointer is returned.
  86. **
  87. ** See sym_insert_name for a description of the name lookup alorithm.
  88. **
  89. ** FORMAL PARAMETERS:
  90. **
  91. ** l_length length of the name not including the null
  92. ** c_text pointer to a null terminated string for name
  93. **
  94. ** IMPLICIT INPUTS:
  95. **
  96. ** sym_az_hash_table the hash table
  97. **
  98. ** IMPLICIT OUTPUTS:
  99. **
  100. ** sym_az_hash_table may be updated with an additional name
  101. **
  102. ** FUNCTION VALUE:
  103. **
  104. ** a pointer to a name entry
  105. **
  106. ** SIDE EFFECTS:
  107. **
  108. ** none
  109. **
  110. **--
  111. **/
  112. sym_name_entry_type
  113. *sym_find_name(l_length, c_text)
  114. int l_length; /* length of name to find */
  115. char *c_text; /* text of the name */
  116. {
  117. sym_name_entry_type *az_current_name;
  118. int l_hash_code;
  119. int l_compare_result;
  120. /* obtain the hash code of for the name */
  121. l_hash_code = hash_function( l_length, c_text );
  122. /*
  123. ** chain along hash chain looking for symbol - exit loop under 3 condition
  124. ** 1) come to the end of the chain: name not found
  125. ** 2) find symbol: return this symbol
  126. ** 3) find node > symbol: name not found
  127. */
  128. for (az_current_name = sym_az_hash_table[ l_hash_code ];
  129. az_current_name != NULL;
  130. az_current_name = az_current_name->az_next_name_entry)
  131. {
  132. l_compare_result = _compare(c_text, az_current_name->c_text);
  133. if (l_compare_result == 0) /* c_text = current name */
  134. {
  135. /* found the name we are looking for */
  136. return az_current_name;
  137. }
  138. if (l_compare_result > 0) /* c_text > current name */
  139. {
  140. /* return NULL - name should be before this spot in list */
  141. return NULL;
  142. }
  143. }
  144. /* came to end of the list without finding the name */
  145. return NULL;
  146. }
  147. /*
  148. **++
  149. ** FUNCTIONAL DESCRIPTION:
  150. **
  151. ** This routine searches for a name entry of the same name as its parameters.
  152. ** If the entry is found, a pointer to that name node is
  153. ** returned as the value of the function. If no entry is found, one is
  154. ** inserted. In this case the value of the function is a pointer to
  155. ** the name entry created.
  156. **
  157. ** Name entries are linked off of a hash table. Those
  158. ** entries that have the same hash code, are sorted according to the
  159. ** collating sequence. Thus the algorithm involves hashing the symbol and
  160. ** then following the chain for that hash code until one of the following
  161. ** conditions is met. 1) the identifier is found, then return a pointer
  162. ** to that name entry. 2) come to the end of the chain or a name
  163. ** entry that comes later in the collating sequence than the symbol being
  164. ** searched for. In this case the name is inserted just prior to this
  165. ** point in the chain.
  166. **
  167. ** FORMAL PARAMETERS:
  168. **
  169. ** l_length length of the name not including the null
  170. ** c_text pointer to a null terminated string for name
  171. **
  172. ** IMPLICIT INPUTS:
  173. **
  174. ** sym_az_hash_table the hash table
  175. **
  176. ** IMPLICIT OUTPUTS:
  177. **
  178. ** sym_az_hash_table may be updated with an additional name
  179. **
  180. ** FUNCTION VALUE:
  181. **
  182. ** a pointer to a name entry
  183. **
  184. ** SIDE EFFECTS:
  185. **
  186. ** may create a name entry and update the hash table
  187. **
  188. **--
  189. **/
  190. sym_name_entry_type *sym_insert_name(l_length, c_text)
  191. int l_length; /* length of name to insert */
  192. char *c_text; /* text of the name */
  193. {
  194. sym_name_entry_type *az_previous_name;
  195. sym_name_entry_type *az_current_name;
  196. sym_name_entry_type *az_new_name;
  197. int l_hash_code;
  198. int l_compare_result;
  199. /*
  200. ** algorithm keeps 2 pointers, one for the previous name and one
  201. ** for the current name. This permits easy insertion of a new name
  202. */
  203. /* obtain the hash code of for the name */
  204. l_hash_code = hash_function( l_length, c_text );
  205. /*
  206. ** chain along hash chain looking for symbol - exit loop under 3 condition
  207. ** 1) come to the end of the chain: insert new node on end
  208. ** 2) find symbol: return this symbol
  209. ** 3) find node > symbol: insert new node prior to current node
  210. */
  211. for (az_current_name = sym_az_hash_table[ l_hash_code ],
  212. az_previous_name = NULL;
  213. az_current_name != NULL;
  214. az_previous_name = az_current_name,
  215. az_current_name = az_current_name->az_next_name_entry)
  216. {
  217. l_compare_result = _compare(c_text, az_current_name->c_text);
  218. if (l_compare_result == 0) /* c_text = current name */
  219. {
  220. /* found the name we are looking for */
  221. return az_current_name;
  222. }
  223. if (l_compare_result > 0) /* c_text > current name */
  224. {
  225. /* exit the loop to insert just prior to current name */
  226. goto insert_name;
  227. }
  228. }
  229. insert_name:
  230. /*
  231. ** name is not in the table so it must be inserted between the
  232. ** az_previous_name and az_current_name entries.
  233. */
  234. /* allocate and initialize the name entry */
  235. az_new_name = (sym_name_entry_type *)
  236. sem_allocate_node (sym_k_name_entry,
  237. sym_k_name_entry_size + l_length + 1);
  238. az_new_name->header.b_type = l_length; /* b_type holds length */
  239. az_new_name->az_object = NULL;
  240. az_new_name->az_cycle_id = 0;
  241. _move( az_new_name->c_text, c_text, l_length+1 );
  242. /*
  243. ** link the name entry into the hash table
  244. */
  245. az_new_name->az_next_name_entry = az_current_name;
  246. if (az_previous_name == NULL)
  247. sym_az_hash_table[ l_hash_code ] = az_new_name;
  248. else
  249. az_previous_name->az_next_name_entry =
  250. (sym_name_entry_type *) az_new_name;
  251. return az_new_name;
  252. }
  253. /*
  254. **++
  255. ** FUNCTIONAL DESCRIPTION:
  256. **
  257. ** This procedure is a hashing function. It takes a length and a
  258. ** pointer to a value. Using this value as a string, the function
  259. ** returns an integer in the range of 0 to sym_k_hash_table_limit-1.
  260. **
  261. ** FORMAL PARAMETERS:
  262. **
  263. ** l_length length of the value in bytes not including null
  264. ** c_value a null terminated string
  265. **
  266. ** IMPLICIT INPUTS:
  267. **
  268. ** sym_k_hash_table_limit
  269. **
  270. ** IMPLICIT OUTPUTS:
  271. **
  272. ** none
  273. **
  274. ** FUNCTION VALUE:
  275. **
  276. ** integer (the hash code) in range 0 to sym_k_hash_table_limit-1
  277. **
  278. ** SIDE EFFECTS:
  279. **
  280. ** none
  281. **
  282. **--
  283. **/
  284. int hash_function(l_length, c_value)
  285. int l_length;
  286. char *c_value;
  287. {
  288. #ifdef WORD64
  289. #define _shift 3
  290. static unsigned int XmConst mask[ 8 ] =
  291. { 0x00000000000000FF, 0x000000000000FFFF,
  292. 0x0000000000FFFFFF, 0x00000000FFFFFFFF,
  293. 0x00000000FFFFFFFF, 0x0000FFFFFFFFFFFF,
  294. 0x00FFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, };
  295. #elif defined (LONG64)
  296. #define _shift 3
  297. static long XmConst mask[ 8 ] =
  298. { 0x00000000000000FF, 0x000000000000FFFF,
  299. 0x0000000000FFFFFF, 0x00000000FFFFFFFF,
  300. 0x00000000FFFFFFFF, 0x0000FFFFFFFFFFFF,
  301. 0x00FFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, };
  302. #else
  303. #define _shift 2
  304. static unsigned int XmConst mask[ 4 ] =
  305. { 0x000000FF, 0x0000FFFF, 0x00FFFFFF, 0xFFFFFFFF };
  306. #endif
  307. #ifdef LONG64
  308. long l_hash_code;
  309. long al_value[20];
  310. #else
  311. int l_hash_code;
  312. int al_value[20];
  313. #endif
  314. int l_limit;
  315. int l_extra;
  316. int i;
  317. l_limit = (l_length-1) >> _shift; /* divide by wordsize */
  318. l_extra = (l_length-1) & _slm; /* remainder from divide by wordsize */
  319. #ifdef LONG64
  320. bzero((char *)al_value, sizeof(long) * 20);
  321. #else
  322. bzero((char *)al_value, sizeof(int) * 20);
  323. #endif
  324. strncpy((char *)al_value, c_value, l_length);
  325. l_hash_code = 0;
  326. for (i = 0; i < l_limit; i++)
  327. {
  328. l_hash_code = l_hash_code ^ al_value[ i ];
  329. }
  330. l_hash_code = l_hash_code ^ (al_value[ i ] & mask[ l_extra ]);
  331. return (int)(l_hash_code % sym_k_hash_table_limit);
  332. }
  333. #if debug_version
  334. /*
  335. **++
  336. ** FUNCTIONAL DESCRIPTION:
  337. **
  338. ** This debugging routine will dump out the name entries linked
  339. ** from the hash table.
  340. **
  341. ** FORMAL PARAMETERS:
  342. **
  343. ** none
  344. **
  345. ** IMPLICIT INPUTS:
  346. **
  347. ** sym_az_hash_table
  348. **
  349. ** IMPLICIT OUTPUTS:
  350. **
  351. ** none
  352. **
  353. ** FUNCTION VALUE:
  354. **
  355. ** void
  356. **
  357. ** SIDE EFFECTS:
  358. **
  359. ** prints out the hash table
  360. **
  361. **--
  362. **/
  363. void sym_dump_hash_table()
  364. {
  365. int i;
  366. int total_count;
  367. int max_length;
  368. int empty_count;
  369. total_count = 0;
  370. empty_count = 0;
  371. max_length = 0;
  372. for (i=0; i<sym_k_hash_table_limit; i++)
  373. {
  374. int bucket_count;
  375. sym_name_entry_type *az_name;
  376. bucket_count = 0;
  377. for (az_name = sym_az_hash_table[ i ];
  378. az_name != NULL;
  379. az_name = az_name->az_next_name_entry)
  380. {
  381. bucket_count++;
  382. _debug_output("\t %s \n", az_name->c_text);
  383. }
  384. total_count += bucket_count;
  385. if (bucket_count == 0)
  386. empty_count++;
  387. max_length = ( max_length > bucket_count )? max_length : bucket_count;
  388. _debug_output("bucket: %d length: %d\n", i, bucket_count);
  389. }
  390. _debug_output("name count: %d \n empty count: %d \n max length: %d",
  391. total_count, empty_count, max_length );
  392. }
  393. #endif