~ubuntu-branches/ubuntu/quantal/openmotif/quantal

« back to all changes in this revision

Viewing changes to lib/Mrm/Mrmwci.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Bauer
  • Date: 2010-06-23 12:12:31 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100623121231-u89gxdp51sg9wjj2
Tags: 2.3.0-1
* New Maintainer (Closes: #379258) 
* Acknowledge NMU changes
* New upstream release (Closes: #494375)
* Get rid of security patches as they are already part of new upstream
  release (00-xpmvuln.openmotif.patch, 342092-CVE-2005-3964.patch)
* Bump Standards to 3.8.4
* Added {misc:Depends} to make the package lintian cleaner
* Fix weak-library-dev-dependency by adding ${binary:Version}) for the
  -dev Package of openmotif
* Let package depend on autotools-dev to use newer autotools-helper-files
* Work around an autoconf-bug (Gentoo-Bug #1475)
* Added Client-side anti-aliased fonts support via XFT
* Added UTF-8 and UTF8_STRING atom support
* Ability to show text and pixmaps in Label, LabelGadget and all
  derived widgets
* Support of PNG/JPEG image formats in the same way as XPM is supported
* Increase FILE_OFFSET_BITS to 64 to show files >2GB in file-selector
  Idea taken from Magne Oestlyngen (Closes: #288537)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 *  @OPENGROUP_COPYRIGHT@
 
3
 *  COPYRIGHT NOTICE
 
4
 *  Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
 
5
 *  Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group
 
6
 *  ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for
 
7
 *  the full copyright text.
 
8
 *  
 
9
 *  This software is subject to an open license. It may only be
 
10
 *  used on, with or for operating systems which are themselves open
 
11
 *  source systems. You must contact The Open Group for a license
 
12
 *  allowing distribution and sublicensing of this software on, with,
 
13
 *  or for operating systems which are not Open Source programs.
 
14
 *  
 
15
 *  See http://www.opengroup.org/openmotif/license for full
 
16
 *  details of the license agreement. Any use, reproduction, or
 
17
 *  distribution of the program constitutes recipient's acceptance of
 
18
 *  this agreement.
 
19
 *  
 
20
 *  EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
 
21
 *  PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 
22
 *  KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
 
23
 *  WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
 
24
 *  OR FITNESS FOR A PARTICULAR PURPOSE
 
25
 *  
 
26
 *  EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
 
27
 *  NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT,
 
28
 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
29
 *  DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
 
30
 *  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
31
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 
32
 *  ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
 
33
 *  EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
 
34
 *  POSSIBILITY OF SUCH DAMAGES.
 
35
 */ 
 
36
/* 
 
37
 * HISTORY
 
38
 */ 
 
39
#ifdef HAVE_CONFIG_H
 
40
#include <config.h>
 
41
#endif
 
42
 
 
43
 
 
44
#ifdef REV_INFO
 
45
#ifndef lint
 
46
static char rcsid[] = "$TOG: Mrmwci.c /main/16 1999/05/19 15:25:58 mgreess $"
 
47
#endif
 
48
#endif
 
49
 
 
50
/*                                                                      *
 
51
 * (c) Copyright 1996 Hewlett-Packard Company                           *
 
52
 * (c) Copyright 1996 International Business Machines Corp.             *
 
53
 * (c) Copyright 1996 Sun Microsystems, Inc.                            *
 
54
 * (c) Copyright 1996 Novell, Inc.                                      *
 
55
 * (c) Copyright 1989, 1990, 1996 Digital Equipment Corporation.        *
 
56
 * (c) Copyright 1996 FUJITSU LIMITED.                                  *
 
57
 * (c) Copyright 1996 Hitachi.                                          *
 
58
 */
 
59
 
 
60
/*
 
61
 *++
 
62
 *  FACILITY:
 
63
 *
 
64
 *      UIL Resource Manager (URM):
 
65
 *
 
66
 *  ABSTRACT:
 
67
 *
 
68
 *      This module holds all routines, structures, and structure definitions
 
69
 *      required for the FT1 widget class information package (WCI). This
 
70
 *      package provides routines which register information about widget
 
71
 *      classes, and which retrieve information about widget classes
 
72
 *      as required by URM.
 
73
 *
 
74
 *--
 
75
 */
 
76
 
 
77
 
 
78
/*
 
79
 *
 
80
 *  INCLUDE FILES
 
81
 *
 
82
 */
 
83
 
 
84
#include <stdio.h>
 
85
#include <X11/IntrinsicP.h>
 
86
#include <X11/CoreP.h>
 
87
 
 
88
#include <Mrm/MrmAppl.h>
 
89
#include <Mrm/Mrm.h>
 
90
 
 
91
#include "MrmMsgI.h"
 
92
 
 
93
/*
 
94
 *
 
95
 *  TABLE OF CONTENTS
 
96
 *
 
97
 */
 
98
static int hash_function ( int l_length , char *c_value );
 
99
 
 
100
 
 
101
 
 
102
/*
 
103
 *
 
104
 *  GLOBAL VARIABLE DECLARATIONS
 
105
 *
 
106
 */
 
107
 
 
108
/*
 
109
 * The list of registered classes, so they can be searched.
 
110
 */
 
111
externaldef(urm__wci) WCIClassDescPtr   wci_cldesc_list = NULL;
 
112
 
 
113
/*
 
114
 *
 
115
 *  OWN VARIABLE DECLARATIONS
 
116
 *
 
117
 */
 
118
 
 
119
 
 
120
/*
 
121
**  Hash tables
 
122
*/
 
123
 
 
124
/*  The hash tables are initialized to NULL by default. */
 
125
static Boolean                  hash_hash_inited = FALSE;
 
126
static URMHashTableEntryPtr     hash_az_hash_table [k_hash_table_size];
 
127
static Boolean                  cldesc_hash_inited = FALSE;
 
128
static URMHashTableEntryPtr     cldesc_hash_table [k_hash_table_size];
 
129
 
 
130
 
 
131
 
 
132
/*
 
133
 *++
 
134
 *
 
135
 *
 
136
 *  PROCEDURE DESCRIPTION:
 
137
 *
 
138
 *      MrmRegisterClass saves the information needed to access the widget
 
139
 *      creation routine using the information in URM databases. 
 
140
 *      type conversion of arglists.
 
141
 *
 
142
 *  FORMAL PARAMETERS:
 
143
 *
 
144
 *      class_code              NOW UNUSED
 
145
 *      class_name              NOW UNUSED
 
146
 *      create_name             The case-sensitive name of the low-level
 
147
 *                              create routine for the class; an example
 
148
 *                              from the Motif toolkit is XmLabelCreate.
 
149
 *                              Arguments are (parent, name, arglist, argcount)
 
150
 *                              The string which names the class in UIL.
 
151
 *      creator                 The low-level routine named create_name
 
152
 *      class_record            The toolkit class record for the class
 
153
 *
 
154
 *  IMPLICIT INPUTS:
 
155
 *
 
156
 *  IMPLICIT OUTPUTS:
 
157
 *
 
158
 *  FUNCTION VALUE:
 
159
 *
 
160
 *      MrmSUCCESS      operation succeeded
 
161
 *      MrmFAILURE      failure allocating class descriptor
 
162
 *
 
163
 *  SIDE EFFECTS:
 
164
 *
 
165
 *--
 
166
 */
 
167
 
 
168
/*ARGSUSED*/
 
169
Cardinal 
 
170
MrmRegisterClass (
 
171
#if NeedWidePrototypes
 
172
                  int                   class_code, /* unused */
 
173
#else
 
174
                  MrmType               class_code, /* unused */
 
175
#endif 
 
176
                  String                class_name, /* unused */
 
177
                  String                create_name,
 
178
                  Widget                (* creator) (),
 
179
                  WidgetClass           class_record)
 
180
{
 
181
  Cardinal      status = MrmRegisterClassWithCleanup(
 
182
                                class_code, class_name,
 
183
                                create_name, creator,
 
184
                                class_record, NULL);
 
185
  return status;
 
186
}
 
187
 
 
188
/*ARGSUSED*/
 
189
Cardinal 
 
190
MrmRegisterClassWithCleanup (
 
191
#if NeedWidePrototypes
 
192
                  int                   class_code, /* unused */
 
193
#else
 
194
                  MrmType               class_code, /* unused */
 
195
#endif 
 
196
                  String                class_name, /* unused */
 
197
                  String                create_name,
 
198
                  Widget                (* creator) (),
 
199
                  WidgetClass           class_record,
 
200
                  void                  (* cleanup) ())
 
201
{
 
202
  /*
 
203
   *  Local variables
 
204
   */
 
205
  WCIClassDescPtr       cldesc;         /* creator descriptor being written */
 
206
  URMHashTableEntryPtr  hash_entry;     /* new hash entry */
 
207
 
 
208
 
 
209
  _MrmProcessLock();
 
210
  /*
 
211
   * Allocate and fill in a new descriptor
 
212
   */
 
213
  if (create_name == NULL) 
 
214
    {
 
215
      _MrmProcessUnlock();
 
216
      return MrmFAILURE;
 
217
    }
 
218
  cldesc = (WCIClassDescPtr) XtMalloc (sizeof(WCIClassDesc) +
 
219
                                       strlen(create_name) + 1);
 
220
  if ( cldesc == NULL )
 
221
    {
 
222
      _MrmProcessUnlock();
 
223
      return MrmFAILURE;
 
224
    }
 
225
  cldesc->creator_name = (String) cldesc + sizeof(WCIClassDesc);
 
226
  strcpy (cldesc->creator_name, create_name);
 
227
  cldesc->validation = URMWCIClassDescValid;
 
228
  cldesc->next_desc = wci_cldesc_list;
 
229
  wci_cldesc_list = cldesc;
 
230
  cldesc->creator = creator;
 
231
  cldesc->class_record = class_record;
 
232
  cldesc->cleanup = cleanup;
 
233
 
 
234
  /*
 
235
   * Enter the descriptor in the descriptor hash table
 
236
   */
 
237
  hash_initialize (cldesc_hash_table, &cldesc_hash_inited);
 
238
  hash_entry = (URMHashTableEntryPtr)
 
239
    hash_insert_name (cldesc_hash_table, cldesc->creator_name);
 
240
  /* Begin fixing CR 5573 */
 
241
  if (hash_entry->az_value != NULL)
 
242
    XtFree ((char *) hash_entry->az_value);
 
243
  /* End fixing CR 5573 */
 
244
  hash_entry->az_value = (char *) cldesc;
 
245
 
 
246
  _MrmProcessUnlock();
 
247
  return MrmSUCCESS;
 
248
 
 
249
}
 
250
 
 
251
 
 
252
Cardinal 
 
253
Urm__WCI_UnregisterName (String                 name)
 
254
{
 
255
  /*
 
256
   * Make sure the hash table is initialized
 
257
   */
 
258
  hash_initialize (hash_az_hash_table, &hash_hash_inited);
 
259
  hash_delete_name (hash_az_hash_table, name);
 
260
 
 
261
  return MrmSUCCESS;    /* in any case */
 
262
}
 
263
 
 
264
 
 
265
/*
 
266
 *++
 
267
 *
 
268
 *  PROCEDURE DESCRIPTION:
 
269
 *
 
270
 *      This routine inserts the names and their associated values into
 
271
 *      the hash table.  No check for duplicate names is made - new
 
272
 *      values for duplicate names will override the previous value.
 
273
 *
 
274
 *  FORMAL PARAMETERS:
 
275
 *
 
276
 *      names           A vector of case-sensitive callback routine names.
 
277
 *      values          A vector of the corresponding routine addresses
 
278
 *      num_cb          The number of entries in names and values.
 
279
 *
 
280
 *  IMPLICIT INPUTS:
 
281
 *
 
282
 *  IMPLICIT OUTPUTS:
 
283
 *
 
284
 *  FUNCTION VALUE:
 
285
 *
 
286
 *      MrmSUCCESS      operation succeeded
 
287
 *
 
288
 *  SIDE EFFECTS:
 
289
 *
 
290
 *--
 
291
 */
 
292
 
 
293
Cardinal 
 
294
Urm__WCI_RegisterNames (String                  *names,
 
295
                        XtPointer               *values,
 
296
                        MrmCount                num_cb)
 
297
{
 
298
 
 
299
  int                   ndx;
 
300
  URMHashTableEntryPtr  hash_entry;
 
301
  char                  *current_name;
 
302
  char                  *current_value;
 
303
 
 
304
 
 
305
  /*
 
306
   * Make sure the hash table is initialized
 
307
   */
 
308
  hash_initialize (hash_az_hash_table, &hash_hash_inited);
 
309
 
 
310
  /*
 
311
   * Store each name-value pair in the hash table.
 
312
   */
 
313
  for (ndx = 0 ; ndx < num_cb ; ndx++)
 
314
    {
 
315
      current_name = names [ndx];
 
316
      current_value = values [ndx];
 
317
      hash_entry = (URMHashTableEntryPtr)
 
318
        hash_insert_name (hash_az_hash_table, current_name);
 
319
      hash_entry -> az_value = current_value;
 
320
    }
 
321
 
 
322
  return MrmSUCCESS;
 
323
 
 
324
}
 
325
 
 
326
 
 
327
 
 
328
/*
 
329
 *++
 
330
 *
 
331
 *  PROCEDURE DESCRIPTION:
 
332
 *
 
333
 *      This routin returns a pointer to the class descriptor for a class.
 
334
 *      The descriptor hash table is used to look up descriptors.
 
335
 *
 
336
 *  FORMAL PARAMETERS:
 
337
 *
 
338
 *      class_name      Class name if class_code is URMwcUnknown
 
339
 *      class_return    To return pointer to class descriptor
 
340
 *
 
341
 *  IMPLICIT INPUTS:
 
342
 *
 
343
 *  IMPLICIT OUTPUTS:
 
344
 *
 
345
 *  FUNCTION VALUE:
 
346
 *
 
347
 *      MrmSUCCESS      operation succeeded
 
348
 *      MrmNOT_FOUND    descriptor not found
 
349
 *
 
350
 *  SIDE EFFECTS:
 
351
 *
 
352
 *--
 
353
 */
 
354
 
 
355
Cardinal 
 
356
Urm__WCI_LookupClassDescriptor (String          class_name,
 
357
                                WCIClassDescPtr *class_return)
 
358
{
 
359
  /*
 
360
   *  Local variables
 
361
   */
 
362
  URMHashTableEntryPtr  hash_entry;     /* hash entry found */
 
363
  char                  err_msg[300];
 
364
 
 
365
 
 
366
  /*
 
367
   * Find a hash entry, and return the value.
 
368
   */
 
369
  hash_entry = (URMHashTableEntryPtr)
 
370
    hash_find_name (cldesc_hash_table, class_name);
 
371
  if ( hash_entry == NULL )
 
372
    {
 
373
      *class_return = NULL;
 
374
      sprintf (err_msg, _MrmMMsg_0051, class_name);
 
375
      return Urm__UT_Error ("Urm__WCI_LookupClassDescriptor",
 
376
                            err_msg, NULL, NULL, MrmNOT_FOUND);
 
377
    }
 
378
  *class_return = (WCIClassDescPtr) hash_entry->az_value;
 
379
  return MrmSUCCESS;
 
380
 
 
381
}
 
382
 
 
383
 
 
384
 
 
385
/*
 
386
 *++
 
387
 *
 
388
 *  PROCEDURE DESCRIPTION:
 
389
 *
 
390
 *      This routine locates a class record for a given class name,
 
391
 *      and returns the widget class record associated with it.
 
392
 *      It searches for a match on either the name in the class record
 
393
 *      or the creation routine name.
 
394
 *
 
395
 *  FORMAL PARAMETERS:
 
396
 *
 
397
 *      clname          the display name of the class
 
398
 *
 
399
 *  IMPLICIT INPUTS:
 
400
 *
 
401
 *  IMPLICIT OUTPUTS:
 
402
 *
 
403
 *  FUNCTION VALUE:
 
404
 *
 
405
 *      Class record pointer, or NULL if not found
 
406
 *
 
407
 *  SIDE EFFECTS:
 
408
 *
 
409
 *--
 
410
 */
 
411
 
 
412
WidgetClass 
 
413
Urm__WCI_GetClRecOfName (String         clname)
 
414
{
 
415
  /*
 
416
   *  Local variables
 
417
   */
 
418
  WCIClassDescPtr               cldesc;         /* current class */
 
419
 
 
420
  /*
 
421
   * Search the class list
 
422
   */
 
423
  for ( cldesc=wci_cldesc_list ; cldesc!=NULL ; cldesc=cldesc->next_desc)
 
424
    {
 
425
      if ( strcmp(clname,cldesc->creator_name) == 0 )
 
426
        return cldesc->class_record;
 
427
      if ( cldesc->class_record == NULL ) continue;
 
428
      if ( strcmp(clname,cldesc->class_record->core_class.class_name) == 0 )
 
429
        return cldesc->class_record;
 
430
    }
 
431
 
 
432
  return NULL;
 
433
 
 
434
}
 
435
 
 
436
 
 
437
 
 
438
/*
 
439
 *++
 
440
 *
 
441
 *  PROCEDURE DESCRIPTION:
 
442
 *
 
443
 *      This routine gets, from the hash table, the value that corresponds
 
444
 *      to the given name.  If no match is found, NULL is returned.
 
445
 *
 
446
 *  FORMAL PARAMETERS:
 
447
 *
 
448
 *      name            case-sensitive name to be matched
 
449
 *      value_return    to return value.
 
450
 *
 
451
 *  IMPLICIT INPUTS:
 
452
 *
 
453
 *  IMPLICIT OUTPUTS:
 
454
 *
 
455
 *  FUNCTION VALUE:
 
456
 *
 
457
 *      MrmSUCCESS      operation succeeded
 
458
 *      MrmNOT_FOUND    no match found
 
459
 *
 
460
 *  SIDE EFFECTS:
 
461
 *
 
462
 *--
 
463
 */
 
464
 
 
465
Cardinal 
 
466
Urm__WCI_LookupRegisteredName (String           name,
 
467
                               XtPointer        *value_return)
 
468
{
 
469
 
 
470
  URMHashTableEntryPtr  hash_entry;
 
471
 
 
472
 
 
473
  hash_entry = (URMHashTableEntryPtr)
 
474
    hash_find_name (hash_az_hash_table, name);
 
475
 
 
476
  if (hash_entry == NULL)
 
477
    {
 
478
      *value_return = NULL;
 
479
      return MrmNOT_FOUND;
 
480
    }
 
481
  else
 
482
    {
 
483
      *value_return = hash_entry->az_value;
 
484
      return MrmSUCCESS;
 
485
    }
 
486
 
 
487
}
 
488
 
 
489
 
 
490
 
 
491
/*
 
492
**++
 
493
**  FUNCTIONAL DESCRIPTION:
 
494
**
 
495
**  This routine initializes a hash table.
 
496
**
 
497
**  FORMAL PARAMETERS:
 
498
**
 
499
**      htable          the hash table to initialize
 
500
**      initflag        if TRUE, the table is already initialized
 
501
**
 
502
**  IMPLICIT INPUTS:
 
503
**
 
504
**  IMPLICIT OUTPUTS:
 
505
**
 
506
**      none
 
507
**
 
508
**  FUNCTION VALUE:
 
509
**
 
510
**  SIDE EFFECTS:
 
511
**
 
512
**      none
 
513
**
 
514
**--
 
515
**/
 
516
 
 
517
void 
 
518
hash_initialize (URMHashTableEntryPtr   *htable,
 
519
                 Boolean                *initflag)
 
520
{
 
521
  int                   ndx;    /* loop index */
 
522
 
 
523
 
 
524
  /*
 
525
   * Initialize only once
 
526
   */
 
527
  if ( *initflag )
 
528
    return;
 
529
  for ( ndx=0 ; ndx<k_hash_table_size ; ndx++ )
 
530
    htable[ndx] = NULL;
 
531
  *initflag = TRUE;
 
532
 
 
533
}
 
534
 
 
535
 
 
536
 
 
537
/*
 
538
**++
 
539
**  FUNCTIONAL DESCRIPTION:
 
540
**
 
541
**  This routine searches for a hash table entry of the same name
 
542
**  as its parameters.  If the entry is found, a pointer to the
 
543
**  found hash table entry is returned as the value of the function.
 
544
**  If no entry is found, a NULL pointer is returned.
 
545
**
 
546
**  FORMAL PARAMETERS:
 
547
**
 
548
**      htable          the hash table to search
 
549
**      c_text          pointer to a null terminated string for name
 
550
**
 
551
**  IMPLICIT INPUTS:
 
552
**
 
553
**  IMPLICIT OUTPUTS:
 
554
**
 
555
**      none
 
556
**
 
557
**  FUNCTION VALUE:
 
558
**
 
559
**      a pointer to a hash table entry, or NULL
 
560
**
 
561
**  SIDE EFFECTS:
 
562
**
 
563
**      none
 
564
**
 
565
**--
 
566
**/
 
567
 
 
568
URMHashTableEntryPtr 
 
569
hash_find_name (URMHashTableEntryPtr    *htable,
 
570
                char                    *c_text)
 
571
{
 
572
  int                           l_length;
 
573
  URMHashTableEntryPtr  az_current_name;
 
574
  int                           l_hash_code;
 
575
  int                           l_compare_result;
 
576
 
 
577
  if (c_text == NULL) return(NULL);
 
578
 
 
579
  /* obtain the hash code for the name */
 
580
 
 
581
  l_length = strlen (c_text);
 
582
  l_hash_code = hash_function( l_length, c_text );
 
583
 
 
584
  /*
 
585
  **  chain along hash chain looking for symbol - exit loop under 3 condition
 
586
  **        1) come to the end of the chain: name not found
 
587
  **        2) find symbol: return this symbol
 
588
  **        3) find node > symbol: name not found
 
589
  */
 
590
 
 
591
  for (az_current_name = htable[ l_hash_code ];
 
592
       az_current_name != NULL;
 
593
       az_current_name = az_current_name->az_next_entry)
 
594
    {
 
595
      l_compare_result = strcmp (c_text, az_current_name->c_text);
 
596
 
 
597
      if (l_compare_result == 0)        /* c_text = current name */
 
598
        {
 
599
          /* found the entry we are looking for */
 
600
 
 
601
          return az_current_name;
 
602
        }
 
603
 
 
604
      if (l_compare_result > 0) /* c_text > current name */
 
605
        {
 
606
          /* return NULL - name should be before this spot in list */
 
607
 
 
608
          return (URMHashTableEntryPtr) NULL;
 
609
        }
 
610
 
 
611
    }
 
612
 
 
613
  /* came to end of the list without finding the name */
 
614
 
 
615
  return (URMHashTableEntryPtr) NULL;
 
616
}
 
617
 
 
618
 
 
619
 
 
620
/*
 
621
**++
 
622
**  FUNCTIONAL DESCRIPTION:
 
623
**
 
624
**  This routine searches for a name entry of the same name as its parameters.
 
625
**  If the entry is found, a pointer to that entry node is 
 
626
**  returned as the value of the function.  If no entry is found, one is 
 
627
**  allocated and inserted.  In this case the value of the function is
 
628
**  a pointer to the name entry created.
 
629
**
 
630
**  Name entries are linked off of a hash table.  Those
 
631
**  entries that have the same hash code, are sorted according to the
 
632
**  collating sequence.  Thus the algorithm involves hashing the symbol and
 
633
**  then following the chain for that hash code until one of the following
 
634
**  conditions is met.  1) the identifier is found, then return a pointer
 
635
**  to that entry.  2) come to the end of the chain or a hash table
 
636
**  entry that comes later in the collating sequence than the symbol being
 
637
**  searched for.  In this case the name is inserted just prior to this
 
638
**  point in the chain.
 
639
**
 
640
**  FORMAL PARAMETERS:
 
641
**
 
642
**      htable          the hash table to update
 
643
**      c_text          pointer to a null terminated string for name
 
644
**
 
645
**  IMPLICIT INPUTS:
 
646
**
 
647
**  IMPLICIT OUTPUTS:
 
648
**
 
649
**      htable   may be updated with an additional name
 
650
**
 
651
**  FUNCTION VALUE:
 
652
**
 
653
**      a pointer to a hash table entry
 
654
**
 
655
**  SIDE EFFECTS:
 
656
**
 
657
**      may create a new entry and update the hash table
 
658
**
 
659
**--
 
660
**/
 
661
 
 
662
URMHashTableEntryPtr 
 
663
hash_insert_name (URMHashTableEntryPtr  *htable,
 
664
                  char                  *c_text)
 
665
{
 
666
  int                           l_length;
 
667
  URMHashTableEntryPtr  az_previous_name;
 
668
  URMHashTableEntryPtr  az_current_name;
 
669
  URMHashTableEntryPtr  az_new_name;
 
670
  int                           l_hash_code;
 
671
  int                           l_compare_result;
 
672
 
 
673
  /*
 
674
  **  algorithm keeps 2 pointers, one for the previous name and one
 
675
  **  for the current name.  This permits easy insertion of a new name 
 
676
  */
 
677
 
 
678
 
 
679
  /* obtain the hash code of for the name */
 
680
 
 
681
  l_length = strlen (c_text);
 
682
  l_hash_code = hash_function( l_length, c_text );
 
683
 
 
684
  /*
 
685
  **  chain along hash chain looking for symbol - exit loop under 3 condition
 
686
  **        1) come to the end of the chain: insert new node on end
 
687
  **        2) find symbol: return this symbol
 
688
  **        3) find node > symbol: insert new node prior to current node
 
689
  */
 
690
 
 
691
  for (az_current_name = htable[ l_hash_code ],
 
692
         az_previous_name = (URMHashTableEntryPtr) NULL;
 
693
 
 
694
       az_current_name != (URMHashTableEntryPtr) NULL;
 
695
 
 
696
       az_previous_name = az_current_name,
 
697
         az_current_name = az_current_name->az_next_entry)
 
698
    {
 
699
      l_compare_result = strcmp (c_text, az_current_name->c_text);
 
700
        
 
701
      if (l_compare_result == 0)        /* c_text = current name */
 
702
        {
 
703
          /* found the name we are looking for */
 
704
            
 
705
          return az_current_name;
 
706
        }
 
707
        
 
708
      if (l_compare_result > 0) /* c_text > current name */
 
709
        {
 
710
          /* exit the loop to insert just prior to current name */
 
711
            
 
712
          goto insert_name;
 
713
        }
 
714
        
 
715
    }
 
716
    
 
717
insert_name:
 
718
    
 
719
  /*
 
720
  **    name is not in the table so it must be inserted between the
 
721
  **  az_previous_name and az_current_name entries.
 
722
  */
 
723
    
 
724
  /* allocate and initialize the name entry, including the null */
 
725
  az_new_name = (URMHashTableEntryPtr)
 
726
    XtMalloc (sizeof(URMHashTableEntry)+l_length+1);
 
727
    
 
728
  az_new_name -> az_value = (char *) NULL;
 
729
  UrmBCopy (c_text, az_new_name -> c_text, l_length + 1);
 
730
    
 
731
  /*
 
732
  **  link the name entry into the hash table
 
733
  */
 
734
    
 
735
  az_new_name->az_next_entry = az_current_name;
 
736
    
 
737
  if (az_previous_name == (URMHashTableEntryPtr) NULL)
 
738
    htable[ l_hash_code ] = az_new_name;
 
739
  else
 
740
    az_previous_name->az_next_entry = az_new_name;    
 
741
    
 
742
  return az_new_name;
 
743
 
 
744
}
 
745
 
 
746
 
 
747
 
 
748
 
 
749
/*
 
750
**++
 
751
**  FUNCTIONAL DESCRIPTION:
 
752
**
 
753
**  just like hash_insert_name but removes the item instead
 
754
**--
 
755
*/
 
756
 
 
757
URMHashTableEntryPtr 
 
758
hash_delete_name (URMHashTableEntryPtr  *htable,
 
759
                  char                  *c_text)
 
760
{
 
761
  int                           l_length;
 
762
  URMHashTableEntryPtr  az_previous_name;
 
763
  URMHashTableEntryPtr  az_current_name;
 
764
  int                           l_hash_code;
 
765
  int                           l_compare_result;
 
766
 
 
767
  /*
 
768
  **  algorithm keeps 2 pointers, one for the previous name and one
 
769
  **  for the current name.  This permits easy deletion of a name 
 
770
  */
 
771
 
 
772
 
 
773
  /* obtain the hash code of for the name */
 
774
 
 
775
  l_length = strlen (c_text);
 
776
  l_hash_code = hash_function( l_length, c_text );
 
777
 
 
778
  /*
 
779
  **  chain along hash chain looking for symbol - exit loop under 3 condition
 
780
  **        1) come to the end of the chain: too far; return
 
781
  **        2) find symbol: delete
 
782
  **        3) find node > symbol: too far; return
 
783
  */
 
784
 
 
785
  for (az_current_name = htable[ l_hash_code ],
 
786
         az_previous_name = (URMHashTableEntryPtr) NULL;
 
787
 
 
788
       az_current_name != (URMHashTableEntryPtr) NULL;
 
789
 
 
790
       az_previous_name = az_current_name,
 
791
         az_current_name = az_current_name->az_next_entry)
 
792
    {
 
793
      l_compare_result = strcmp (c_text, az_current_name->c_text);
 
794
        
 
795
      if (l_compare_result == 0)        /* c_text = current name */
 
796
        {
 
797
          /* found the name we are looking for */
 
798
          goto delete_name;
 
799
        }
 
800
        
 
801
      if (l_compare_result > 0) /* c_text > current name */
 
802
        {
 
803
          /* return NULL - name should be before this spot in list */
 
804
          return (URMHashTableEntryPtr) NULL;
 
805
        }
 
806
        
 
807
    }
 
808
  /* came to end of the list without finding the name */
 
809
  return (URMHashTableEntryPtr) NULL;
 
810
    
 
811
delete_name:
 
812
    
 
813
  /*
 
814
  **  remove the name entry from the hash table
 
815
  */
 
816
    
 
817
  if (az_previous_name == (URMHashTableEntryPtr) NULL)
 
818
    htable[ l_hash_code ] = az_current_name->az_next_entry;
 
819
  else
 
820
    az_previous_name->az_next_entry = az_current_name->az_next_entry;    
 
821
 
 
822
  XtFree((char*)az_current_name);
 
823
    
 
824
  return (URMHashTableEntryPtr) NULL;
 
825
}
 
826
 
 
827
 
 
828
 
 
829
 
 
830
 
 
831
/*
 
832
**++
 
833
**  FUNCTIONAL DESCRIPTION:
 
834
**
 
835
**      This procedure is a hashing function.  It takes a length and a
 
836
**      pointer to a value.  Using this value as a string, the function
 
837
**      returns an integer in the range of 0 to sym_k_hash_table_limit-1.
 
838
**
 
839
**  FORMAL PARAMETERS:
 
840
**
 
841
**      l_length            length of the value in bytes not including null
 
842
**      c_value             a null terminated string 
 
843
**
 
844
**  IMPLICIT INPUTS:
 
845
**
 
846
**      sym_k_hash_table_limit
 
847
**
 
848
**  IMPLICIT OUTPUTS:
 
849
**
 
850
**      none
 
851
**
 
852
**  FUNCTION VALUE:
 
853
**
 
854
**      integer (the hash code) in range 0 to sym_k_hash_table_limit-1
 
855
**
 
856
**  SIDE EFFECTS:
 
857
**
 
858
**      none
 
859
**
 
860
**--
 
861
**/
 
862
 
 
863
static int 
 
864
hash_function(int       l_length,
 
865
              char      *c_value)
 
866
{
 
867
#ifdef WORD64
 
868
#define _shift 3
 
869
  static unsigned int XmConst   mask[ 8 ] =
 
870
  { 0x00000000000000FF, 0x000000000000FFFF,
 
871
    0x0000000000FFFFFF, 0x00000000FFFFFFFF,
 
872
    0x00000000FFFFFFFF, 0x0000FFFFFFFFFFFF,
 
873
    0x00FFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, };
 
874
#else
 
875
#define _shift 2      
 
876
  static unsigned int XmConst   mask[ 4 ] = 
 
877
  { 0x000000FF, 0x0000FFFF, 0x00FFFFFF, 0xFFFFFFFF };
 
878
#endif
 
879
  unsigned int          l_hash_code;
 
880
  unsigned int  al_value[20];
 
881
  int                   l_limit;
 
882
  int                   l_extra;
 
883
  int                   i;
 
884
 
 
885
  /* BEGIN OSF Fix CR 5232 */
 
886
  /* Don't go past array bounds */
 
887
  if (l_length > (sizeof(int) * 20)) l_length = sizeof(int) * 20;
 
888
  /* END OSF Fix CR 5232 */
 
889
 
 
890
  l_limit = (l_length-1) >> _shift;     /* divide by wordsize */
 
891
  /* BEGIN OSF Fix CR 5232 */
 
892
  l_extra = (l_length-1) & _shift;      /* remainder from divide by wordsize */
 
893
  /* END OSF Fix CR 5232 */
 
894
 
 
895
  bzero((char *)al_value, sizeof(int) * 20);
 
896
  strncpy((char *)al_value, c_value, l_length);
 
897
  l_hash_code = 0;
 
898
 
 
899
  for (i = 0 ; i < l_limit ; i++)
 
900
    l_hash_code = l_hash_code ^ al_value[ i ];
 
901
 
 
902
  l_hash_code = l_hash_code ^ (al_value[ i ] & mask[ l_extra ]);
 
903
 
 
904
  /* BEGIN OSF Fix CR 5232 */
 
905
  /* Make sure result isn't negative */
 
906
  return abs((int)(l_hash_code % k_hash_table_size));
 
907
  /* END OSF Fix CR 5232 */
 
908
}