Files
Lev Kujawski a6ea2a2d52 Centralize catgets() calls through MsgCat
CDE has relied upon catgets() implementations following a relaxed
interpretation of the XPG internationalization standard that ignored
-1, the standard error value returned by catopen, as the catalog
argument. However, this same behavior causes segmentation faults with
the musl C library.

This patch:

- Centralizes (with the exception of ToolTalk) all calls to catopen(),
  catgets(), and catclose() through MsgCat within the DtSvc library.
- Prevents calls to catgets() and catclose() that rely upon
  undefined behavior.
- Eliminates a number of bespoke catgets() wrappers, including multiple
  redundant caching implementations designed to work around a design
  peculiarity in HP/UX.
- Eases building CDE without XPG internationalization support by providing
  the appropriate macros.
2021-06-02 19:55:15 -06:00

1067 lines
31 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* $XConsortium: istr.c /main/4 1995/11/06 18:50:43 rswiston $
*
* @(#)istr.c 1.25 14 Feb 1994 cde_app_builder/src/libAButil
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
*
*/
/*
* istr.c
*
* Implements ISTRING data type.
*
* the istr variable is private, but is made to be used within
* the debugger. To get the value of an ISTRING, use
* print/display debug_istr[iString].
*
* Whenever setting the private variable int_array from within this
* ISTRING * implementation module, use int_array_set macro, as it
* will keep the istr variable up-to-date for debugging clients.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <ab_private/istr.h>
#include "utilP.h"
#define istrP_create_alloced_impl istrP_create_alloced_impl9726039350PrivF
#define istrP_destroy_impl istrP_destroy_impl518283652PrivF
#define istrP_get_string_verify istrP_get_string_verify4521632085PrivF
#define int_array istrP_int_array1809065681PrivD
#define num_count istrP_num_count7608925912PrivD
#define STRN ISTR_PRIVT_STRN
/* #define NUMBUCKETS 211 */
#define NUMBUCKETS 1024
#define NUMBUCKETS_MASK ((unsigned)(NUMBUCKETS-1))
#define BUCKETSIZE 10
#define ARRAYSIZE 100 /* size of and freelist */
typedef struct BUCKET
{
struct BUCKET *next;
int values[BUCKETSIZE];
} BucketRec, *Bucket;
/*
* Public data
*/
STRING Istr_null_string= "(nil)";
STRN *int_array= NULL; /* unique number array */
long num_count = 1; /* unique number counter */
static BucketRec hashtable[NUMBUCKETS];
#ifdef DEBUG
STRN *debug_istr= NULL; /* debugging shortcut for clients (see */
/* comment at top of this file) */
#endif /* DEBUG */
static long *freelist; /* freelist for unused numbers */
static long freecount = 0; /* freelist count */
static long hash_count = 0; /* total number that has been inserted */
static unsigned hashing(
char *p
);
static int insert_array(
int flag,
int val,
char *string
);
static int hash_and_lookupstr(
char *string,
int *hash_val_out_ptr
);
static int hashtable_init(void);
static int istrP_errmsg_noexist(int istr_value);
#define check_init() ((hash_count == 0) && (hashtable_init() >= 0))
#ifdef DEBUG
#define int_array_set(ptr) (int_array = (ptr), debug_istr= int_array)
#else
#define int_array_set(ptr) (int_array = (ptr))
#endif
#define istrP_int_to_client(intVal) ((ISTRING)(intVal))
#define istrP_client_to_int(istrVal) ((long)(istrVal))
#define return_istr(x) return istrP_int_to_client(x)
/*****************************************************************************/
/* EXTERNAL FUNCTIONS */
/*****************************************************************************/
/*
* Allocate a new int for a given string and return the value.
* If the string already exists return the value for the existing int.
*/
ISTRING
istr_create (
STRING string
)
{
int hashval;
long str_exists;
Bucket new_bucket;
int i;
Bucket entry;
check_init();
if (string == NULL)
{
return NULL;
}
/* hashval = hashing(string); */
if ((str_exists = hash_and_lookupstr(string,&hashval )) == -1) /* new entry */
{
entry = &hashtable[hashval];
for (i=0; i< BUCKETSIZE; i++)
{
if (entry->values[i] == -1)
{
if(freecount == 0)
{
entry->values[i] = num_count;
if (insert_array(1,num_count, string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
num_count++;
hash_count++;
return istrP_int_to_client(num_count-1);
}
else
{ /* take int value from freelist */
if(int_array[freelist[freecount-1]].refcount != 0)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 2,
"ISTR: error in allocating space for string\n") );
return NULL;
}
entry->values[i] = freelist[freecount-1];
if (insert_array(1,freelist[freecount-1], string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
freecount--;
return istrP_int_to_client(freelist[freecount]);
}
}
}
while(entry->next != NULL) /* check next bucket */
{
entry = entry->next;
for (i=0; i< BUCKETSIZE; i++)
{
if (entry->values[i] == -1)
{
if (freecount == 0)
{
entry->values[i] = num_count;
if (insert_array(1, num_count, string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
num_count++;
hash_count++;
return istrP_int_to_client(num_count-1);
}
else
{
if(int_array[freelist[freecount-1]].refcount != 0)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 2,
"ISTR: error in allocating space for string\n") );
return NULL;
}
entry->values[i] = freelist[freecount-1];
if (insert_array(1,
freelist[freecount-1], string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
freecount--;
return istrP_int_to_client(freelist[freecount]);
}
}
}
}
/* if get this far, then no space is available in existing bucket,
add new bucket */
new_bucket = (Bucket)malloc (sizeof(BucketRec));
if (new_bucket == NULL)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 3,
"ISTR: error in allocating memory\n") );
return NULL ;
}
for(i=1;i<BUCKETSIZE; i++)
new_bucket->values[i] = -1;
new_bucket->next = NULL;
if (freecount == 0)
{
new_bucket->values[0] = num_count;
entry->next = new_bucket;
if (insert_array(1, num_count, string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
num_count++;
hash_count++;
return istrP_int_to_client(num_count-1);
}
else
{
if(int_array[freelist[freecount-1]].refcount != 0)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 2,
"ISTR: error in allocating space for string\n") );
return NULL;
}
new_bucket->values[0] = freelist[freecount-1];
entry->next = new_bucket;
if (insert_array(1, freelist[freecount-1], string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
freecount--;
return_istr(freelist[freecount]);
}
}
else /* duplicate entry */
{
int_array[str_exists].refcount++;
return istrP_int_to_client(str_exists);
}
}
/*
* Assign a new int for a given allocated string and return the value.
* If the string already exists return the value for the existing int.
*/
ISTRING
istrP_create_alloced_impl(
STRING *string
)
{
int hashval;
long str_exists;
Bucket new_bucket;
int i;
Bucket entry;
check_init();
if (*string == NULL)
{
return NULL;
}
/* hashval = hashing(*string); */
if ((str_exists = hash_and_lookupstr(*string,&hashval)) == -1) /* new entry */
{
entry = &hashtable[hashval];
for (i=0; i< BUCKETSIZE; i++)
{
if (entry->values[i] == -1)
{
if(freecount == 0)
{
entry->values[i] = num_count;
if (insert_array(3,num_count, *string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
num_count++;
hash_count++;
return_istr(num_count-1);
}
else
{ /* take int value from freelist */
if(int_array[freelist[freecount-1]].refcount != 0)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 2,
"ISTR: error in allocating space for string\n") );
return NULL;
}
entry->values[i] = freelist[freecount-1];
if (insert_array(3,freelist[freecount-1], *string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
freecount--;
return_istr(freelist[freecount]);
}
}
}
while(entry->next != NULL) /* go to next bucket */
{
entry = entry->next;
for (i=0; i< BUCKETSIZE; i++)
{
if (entry->values[i] == -1)
{
if (freecount == 0)
{
entry->values[i] = num_count;
if (insert_array(3, num_count, *string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
num_count++;
hash_count++;
return_istr(num_count-1);
}
else
{
if(int_array[freelist[freecount-1]].refcount != 0)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 2,
"ISTR: error in allocating space for string\n") );
return NULL;
}
entry->values[i] = freelist[freecount-1];
if (insert_array(3,
freelist[freecount-1], *string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
freecount--;
return_istr(freelist[freecount]);
}
}
}
}
/* if get this far, then no space is available in existing bucket,
add new bucket */
new_bucket = (Bucket)malloc (sizeof(BucketRec));
if (new_bucket == NULL)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 3,
"ISTR: error in allocating memory\n") );
return NULL ;
}
for(i=1;i<BUCKETSIZE; i++)
new_bucket->values[i] = -1;
new_bucket->next = NULL;
if (freecount == 0)
{
new_bucket->values[0] = num_count;
entry->next = new_bucket;
if (insert_array(3, num_count, *string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
num_count++;
hash_count++;
return_istr(num_count-1);
}
else
{
if(int_array[freelist[freecount-1]].refcount != 0)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 2,
"ISTR: error in allocating space for string\n") );
free(new_bucket);
return NULL;
}
new_bucket->values[0] = freelist[freecount-1];
entry->next = new_bucket;
if (insert_array(3, freelist[freecount-1], *string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
freecount--;
return_istr(freelist[freecount]);
}
}
else /* duplicate entry */
{
int_array[str_exists].refcount++;
if ((*string != int_array[str_exists].str) &&
(*&string != &(int_array[str_exists].str)))
{
free(*string);
*string = NULL;
}
return_istr(str_exists);
}
}
/*
* Assign a new int for a given string and return the value.
* If the string already exists deallocate the existing string
* and assign the new string to the int return the value for
* the existing int.
*/
ISTRING
istr_create_const(
STRING string
)
{
int hashval;
long str_exists;
Bucket new_bucket;
int i;
Bucket entry;
check_init();
if (string == NULL)
{
return NULL;
}
/* hashval = hashing(string); */
if ((str_exists = hash_and_lookupstr(string,&hashval)) == -1) /* new entry */
{
entry = &hashtable[hashval];
for (i=0; i< BUCKETSIZE; i++)
{
if (entry->values[i] == -1)
{
if(freecount == 0)
{ /* no numbers on freelist */
entry->values[i] = num_count;
if (insert_array(2, num_count, string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
num_count++;
hash_count++;
return_istr(num_count-1);
}
else
{ /* take int value from freelist */
if(int_array[freelist[freecount-1]].refcount != 0)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 2,
"ISTR: error in allocating space for string\n") );
return NULL;
}
entry->values[i] = freelist[freecount-1];
if (insert_array(2, freelist[freecount-1], string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
freecount--;
return_istr(freelist[freecount]);
}
}
}
while(entry->next != NULL)
{ /* check next bucket */
entry = entry->next;
for (i=0; i< BUCKETSIZE; i++)
{
if (entry->values[i] == -1)
{
if (freecount == 0)
{
entry->values[i] = num_count;
if (insert_array(2, num_count, string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
num_count++;
hash_count++;
return_istr(num_count-1);
}
else
{
if(int_array[freelist[freecount-1]].refcount != 0)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 2,
"ISTR: error in allocating space for string\n") );
return NULL;
}
entry->values[i] = freelist[freecount-1];
if (insert_array(2,
freelist[freecount-1], string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
freecount--;
return_istr(freelist[freecount]);
}
}
}
}
/* if get this far, then no space is available in existing bucket,
add new bucket */
new_bucket = (Bucket)malloc (sizeof(BucketRec));
if (new_bucket == NULL)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 3,
"ISTR: error in allocating memory\n") );
return NULL ;
}
for(i=1;i<BUCKETSIZE; i++)
{
new_bucket->values[i] = -1;
}
new_bucket->next = NULL;
if (freecount == 0)
{
new_bucket->values[0] = num_count;
entry->next = new_bucket;
if (insert_array(2, num_count, string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
num_count++;
hash_count++;
return_istr(num_count-1);
}
else
{
if(int_array[freelist[freecount-1]].refcount != 0)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 2,
"ISTR: error in allocating space for string\n") );
free(new_bucket);
return NULL;
}
new_bucket->values[0] = freelist[freecount-1];
entry->next = new_bucket;
if (insert_array(2, freelist[freecount-1], string) == -1)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 1,
"ISTR: error in allocating to int array\n") );
return NULL;
}
freecount--;
return_istr(freelist[freecount]);
}
}
else /* duplicate entry */
{
if(int_array[str_exists].read_const == 0)
{ /* change read only string to const string */
if ((string != int_array[str_exists].str) &&
(&string != &(int_array[str_exists].str)))
{
free(int_array[str_exists].str);
int_array[str_exists].str = string;
}
int_array[str_exists].read_const = 1;
}
int_array[str_exists].refcount++;
return_istr(str_exists);
}
}
/*
* Lookup string if find it duplicate the entry and return int value,
* else return NULL.
*/
ISTRING
istr_dup_existing(
STRING string
)
{
int hashval;
long str_exists;
if (string == NULL)
{
return NULL;
}
/* hashval = hashing(string); */
if ((str_exists = hash_and_lookupstr(string,&hashval)) == -1)
{ /* string doesn't exist */
return NULL;
}
else
{
int_array[str_exists].refcount++;
return_istr(str_exists);
}
}
/*
* Deallocate for the string if refcount = 0, else decrement refcount.
* If read_const flag is set then don't deallocate.
* Return -1 if error, else return 1
*/
int
istrP_destroy_impl(
ISTRING *istringClientPtr
)
{
long istring = (long)(*istringClientPtr);
int val; /* hashing value */
int i;
Bucket entry;
static int free_num = 0; /* allocated space in freelist =
free_num * ARRAYSIZE */
if(istring == 0)
{
return 0;
}
if((istring < 0) || (istring >= num_count) ||
((int_array[istring].refcount == 0) &&
(int_array[istring].read_const == 0)))
{
istrP_errmsg_noexist(istring);
return 0;
}
if (int_array[istring].read_const == 1) /* const entry */
{
/* never let refs to const entries drop below 1 */
if (int_array[istring].refcount > 1)
{
int_array[istring].refcount--;
}
(*istringClientPtr) = NULL;
return 0;
}
int_array[istring].refcount--;
if(int_array[istring].refcount == 0)
{ /* remove from hash table */
val = hashing(int_array[istring].str);
entry = &hashtable[val];
for (i =0; i< BUCKETSIZE; i++)
{
if (entry->values[i] == istring)
{
entry->values[i] = -1;
}
}
while(entry->next != NULL)
{
entry = entry->next;
for (i =0; i< BUCKETSIZE; i++)
{
if (entry->values[i] == istring)
{
entry->values[i] = -1;
}
}
}
free(int_array[istring].str);
int_array[istring].str = NULL;
/* put unused int_array location of the freelist */
if(free_num == 0)
{
freelist = (long *)malloc(ARRAYSIZE * sizeof(long));
if (freelist == NULL)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 3,
"ISTR: error in allocating memory\n") );
return 0 ;
}
free_num = 1;
}
if(freecount < (ARRAYSIZE * free_num)) /* put free int value on
freelist */
{
freelist[freecount] = istring;
freecount++;
}
else /* need more freelist space */
{
free_num++;
freelist = (long *)realloc(freelist,
(ARRAYSIZE * free_num) * sizeof(long));
assert(freelist != NULL);
if (freelist == NULL)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 3,
"ISTR: error in allocating memory\n") );
return 0 ;
}
freelist[freecount] = istring;
freecount++;
}
}
/*
* Set the client's variable to NULL
*/
istring = 0;
(*istringClientPtr) = istrP_int_to_client(istring);
return 1;
}
/*
* Increment the string refcounter, and return the string value.
* Return -1 if error
*/
ISTRING
istr_dup(
ISTRING istringClientVal
)
{
long istring= istrP_client_to_int(istringClientVal);
if(istring == 0)
{
return 0;
}
else if((istring < 0) || (istring >= num_count) ||
((int_array[istring].refcount == 0) &&
(int_array[istring].read_const == 0)))
{
istrP_errmsg_noexist(istring);
return NULL;
}
int_array[istring].refcount++;
return_istr(istring);
}
/*
* Return the string name for the given int, return NULL if error
*
* Verifies that the string is valid
*/
STRING
istrP_get_string_verify(
ISTRING istringClientVal
)
{
long istring = istrP_client_to_int(istringClientVal);
if(istring == 0)
{
return NULL;
}
if((istring < 0) || (istring >= num_count) ||
((int_array[istring].refcount == 0) &&
(int_array[istring].read_const == 0)))
{
istrP_errmsg_noexist(istring);
return NULL;
}
return int_array[istring].str;
}
/******************************************************************************/
/* PRIVATE FUNCTIONS */
/******************************************************************************/
/*
* hash function
*/
static unsigned
hashing(
STRING string
)
{
unsigned hash_val = 0;
for (hash_val = 0; *string; ++string)
hash_val = hash_val * 65599 + *string;
return hash_val % NUMBUCKETS;
}
/*
* search hash table for existing strings
*
* Returns int value for string, or -1 if not found
*/
static int
hash_and_lookupstr(
char *string,
int *hash_val_out_ptr
)
{
#define fast_streq(s1,s2) (((s1)[0] == (s2)[0]) && (strcmp(s1,s2) == 0))
unsigned hash_val = 0;
char *stringPtr;
Bucket entry;
int *valuePtr;
int *valuePtrEnd;
int value;
/*
* Get bucket
*/
for (hash_val = 0, stringPtr = string; *stringPtr; ++stringPtr)
hash_val = hash_val * 65599 + *stringPtr;
(*hash_val_out_ptr) = (hash_val &= NUMBUCKETS_MASK);
/*
* Find entry in bucket
*/
for (entry = &hashtable[hash_val]; entry != NULL; entry = entry->next)
{
valuePtr = entry->values;
valuePtrEnd = valuePtr + BUCKETSIZE;
for (; valuePtr != valuePtrEnd; ++valuePtr)
{
value = *valuePtr;
if ( (value >= 0)
&& (fast_streq(int_array[value].str,string)) )
{
return value;
}
}
}
return -1;
#undef fast_streq
}
/*
* Insert the given string into the given array location.
* Return 1 if successful, else return NULL if error.
* Note: int_array[0] unused
*/
static int
insert_array(
int flag,
int val,
char *string
)
{
char *str;
static int array_num =0;
if(hash_count == 0)
{
int_array_set((STRN *)calloc(ARRAYSIZE, sizeof(STRN)));
if (int_array == NULL)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 3,
"ISTR: error in allocating memory\n") );
return 0 ;
}
array_num = 1;
}
if(val < (ARRAYSIZE * array_num)) /* insert into array */
{
int_array[val].refcount =1;
if (flag == 1)
{ /* read only */
str = strdup(string);
int_array[val].read_const = 0;
int_array[val].str = str;
}
else if (flag == 2)
{ /* const */
int_array[val].read_const = 1;
int_array[val].str = string;
}
else /* flag == 3 */
{ /* allocated */
int_array[val].read_const = 0;
int_array[val].str = string;
}
}
else /* need more array space */
{
array_num++;
int_array_set((STRN *)realloc(int_array,
(ARRAYSIZE * array_num) * sizeof(STRN)));
assert(int_array != NULL);
if (int_array == NULL)
{
fprintf(stderr, "%s",
CATGETS(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 3,
"ISTR: error in allocating memory\n") );
return 0 ;
}
int_array[val].refcount =1;
if (flag == 1)
{ /* read only */
str = strdup(string);
int_array[val].read_const = 0;
int_array[val].str = str;
}
else if(flag == 2) /* const */
{
int_array[val].read_const = 1;
int_array[val].str = string;
}
else /*flag == 3*/
{ /* allocated */
int_array[val].read_const = 0;
int_array[val].str = string;
}
}
return 1;
}
static int
hashtable_init(void)
{
int i = 0, j = 0;
for(i=0; i< NUMBUCKETS; i++)
{
hashtable[i].next = NULL;
for (j=0; j < BUCKETSIZE; j++)
{
hashtable[i].values[j] = -1;
}
}
return 0;
}
/*
* Verifies the string exists and is not corrupted.
*/
int
istr_verify(ISTRING istringClientVal)
{
int istring= istrP_client_to_int(istringClientVal);
int return_value = 0;
if (istringClientVal == (ISTRING)NULL)
{
return 0; /* OK */
}
if((istring < 0) || (istring >= num_count) ||
((int_array[istring].refcount == 0) &&
(int_array[istring].read_const == 0)))
{
return_value = -1;
}
return return_value;
}
/*
* This doesn't do anything right now, although it really should.
*/
int
istr_verify_all(void)
{
return 0;
}
static int
istrP_errmsg_noexist(int istr_value)
{
#ifdef DEBUG
fprintf(stderr,"ISTR: the reference string %d doesn't exist\n",
istr_value);
if (util_get_verbosity() >= 3)
{
util_error("Aborting (dumping core).");
abort();
}
#endif /* DEBUG */
return 0;
}