mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Commit several minor changes:
* main.c (print_help): Document `--no-http-keep-alive'. * utils.c (numdigit): Handle negative numbers *correctly*. * hash.c (make_nocase_string_hash_table): Use term "nocase" rather than the confusing "unsigned". * utils.c (string_set_contains): Renamed from string_set_exists. * hash.c (hash_table_contains): Renamed from hash_table_exists. * cookies.c: Move case-insensitive hash tables to hash.c. Published in <sxsheyq9vvl.fsf@florida.arsdigita.de>.
This commit is contained in:
parent
9588e1af80
commit
72eca0976b
@ -1,3 +1,18 @@
|
|||||||
|
2001-05-12 Hrvoje Niksic <hniksic@arsdigita.com>
|
||||||
|
|
||||||
|
* main.c (print_help): Document `--no-http-keep-alive'.
|
||||||
|
|
||||||
|
* utils.c (numdigit): Handle negative numbers *correctly*.
|
||||||
|
|
||||||
|
* hash.c (make_nocase_string_hash_table): Use term "nocase" rather
|
||||||
|
than the confusing "unsigned".
|
||||||
|
|
||||||
|
* utils.c (string_set_contains): Renamed from string_set_exists.
|
||||||
|
|
||||||
|
* hash.c (hash_table_contains): Renamed from hash_table_exists.
|
||||||
|
|
||||||
|
* cookies.c: Move case-insensitive hash tables to hash.c.
|
||||||
|
|
||||||
2001-05-09 Hrvoje Niksic <hniksic@arsdigita.com>
|
2001-05-09 Hrvoje Niksic <hniksic@arsdigita.com>
|
||||||
|
|
||||||
* http.c (gethttp): Before concluding that the file is already
|
* http.c (gethttp): Before concluding that the file is already
|
||||||
|
@ -104,45 +104,15 @@ delete_cookie (struct cookie *cookie)
|
|||||||
xfree (cookie);
|
xfree (cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Functions for cookie-specific hash tables. These are regular hash
|
/* Functions for storing cookies.
|
||||||
tables, but with case-insensitive test and hash functions. */
|
|
||||||
|
|
||||||
/* Like string_hash, but produces the same results regardless of the
|
All cookies can be referenced through cookies_hash_table. The key
|
||||||
case. */
|
in that table is the domain name, and the value is a linked list of
|
||||||
|
all cookies from that domain. Every new cookie is placed on the
|
||||||
|
head of the list. */
|
||||||
|
|
||||||
static unsigned long
|
/* Write "HOST:PORT" to a stack-allocated area and make RESULT point
|
||||||
unsigned_string_hash (const void *key)
|
to that area. RESULT should be a character pointer. Useful for
|
||||||
{
|
|
||||||
const char *p = key;
|
|
||||||
unsigned int h = TOLOWER (*p);
|
|
||||||
|
|
||||||
if (h)
|
|
||||||
for (p += 1; *p != '\0'; p++)
|
|
||||||
h = (h << 5) - h + TOLOWER (*p);
|
|
||||||
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Front-end to strcasecmp. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
unsigned_string_cmp (const void *s1, const void *s2)
|
|
||||||
{
|
|
||||||
return !strcasecmp ((const char *)s1, (const char *)s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Like make_string_hash_table, but uses unsigned_string_hash and
|
|
||||||
unsigned_string_cmp. */
|
|
||||||
|
|
||||||
static struct hash_table *
|
|
||||||
make_unsigned_string_hash_table (int initial_size)
|
|
||||||
{
|
|
||||||
return hash_table_new (initial_size,
|
|
||||||
unsigned_string_hash, unsigned_string_cmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write "HOST:PORT" to RESULT. RESULT should be a pointer, and the
|
|
||||||
memory for the contents is allocated on the stack. Useful for
|
|
||||||
creating HOST:PORT strings, which are the keys in the hash
|
creating HOST:PORT strings, which are the keys in the hash
|
||||||
table. */
|
table. */
|
||||||
|
|
||||||
@ -165,13 +135,6 @@ find_cookie_chain_exact (const char *domain, int port)
|
|||||||
SET_HOSTPORT (domain, port, key);
|
SET_HOSTPORT (domain, port, key);
|
||||||
return hash_table_get (cookies_hash_table, key);
|
return hash_table_get (cookies_hash_table, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Functions for storing cookies.
|
|
||||||
|
|
||||||
All cookies can be referenced through cookies_hash_table. The key
|
|
||||||
in that table is the domain name, and the value is a linked list of
|
|
||||||
all cookies from that domain. Every new cookie is placed on the
|
|
||||||
head of the list. */
|
|
||||||
|
|
||||||
/* Find and return the cookie whose domain, path, and attribute name
|
/* Find and return the cookie whose domain, path, and attribute name
|
||||||
correspond to COOKIE. If found, PREVPTR will point to the location
|
correspond to COOKIE. If found, PREVPTR will point to the location
|
||||||
@ -225,7 +188,7 @@ store_cookie (struct cookie *cookie)
|
|||||||
if (!cookies_hash_table)
|
if (!cookies_hash_table)
|
||||||
/* If the hash table is not initialized, do so now, because we'll
|
/* If the hash table is not initialized, do so now, because we'll
|
||||||
need to store things. */
|
need to store things. */
|
||||||
cookies_hash_table = make_unsigned_string_hash_table (0);
|
cookies_hash_table = make_nocase_string_hash_table (0);
|
||||||
|
|
||||||
/* Initialize hash table key. */
|
/* Initialize hash table key. */
|
||||||
SET_HOSTPORT (cookie->domain, cookie->port, hostport);
|
SET_HOSTPORT (cookie->domain, cookie->port, hostport);
|
||||||
|
98
src/hash.c
98
src/hash.c
@ -54,11 +54,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||||||
The basics are all covered. hash_table_new creates a hash table,
|
The basics are all covered. hash_table_new creates a hash table,
|
||||||
and hash_table_destroy deletes it. hash_table_put establishes a
|
and hash_table_destroy deletes it. hash_table_put establishes a
|
||||||
mapping between a key and a value. hash_table_get retrieves the
|
mapping between a key and a value. hash_table_get retrieves the
|
||||||
value that corresponds to a key. hash_table_exists queries whether
|
value that corresponds to a key. hash_table_contains queries
|
||||||
a key is stored in a table at all. hash_table_remove removes a
|
whether a key is stored in a table at all. hash_table_remove
|
||||||
mapping that corresponds to a key. hash_table_map allows you to
|
removes a mapping that corresponds to a key. hash_table_map allows
|
||||||
map through all the entries in a hash table. hash_table_clear
|
you to map through all the entries in a hash table.
|
||||||
clears all the entries from the hash table.
|
hash_table_clear clears all the entries from the hash table.
|
||||||
|
|
||||||
The number of mappings in a table is not limited, except by the
|
The number of mappings in a table is not limited, except by the
|
||||||
amount of memory. As you add new elements to a table, it regrows
|
amount of memory. As you add new elements to a table, it regrows
|
||||||
@ -242,8 +242,8 @@ find_mapping (struct hash_table *ht, const void *key)
|
|||||||
/* Get the value that corresponds to the key KEY in the hash table HT.
|
/* Get the value that corresponds to the key KEY in the hash table HT.
|
||||||
If no value is found, return NULL. Note that NULL is a legal value
|
If no value is found, return NULL. Note that NULL is a legal value
|
||||||
for value; if you are storing NULLs in your hash table, you can use
|
for value; if you are storing NULLs in your hash table, you can use
|
||||||
hash_table_exists to be sure that a (possibly NULL) value exists in
|
hash_table_contains to be sure that a (possibly NULL) value exists
|
||||||
the table. Or, you can use hash_table_get_pair instead of this
|
in the table. Or, you can use hash_table_get_pair instead of this
|
||||||
function. */
|
function. */
|
||||||
|
|
||||||
void *
|
void *
|
||||||
@ -277,10 +277,10 @@ hash_table_get_pair (struct hash_table *ht, const void *lookup_key,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 1 if KEY exists in HT, 0 otherwise. */
|
/* Return 1 if HT contains KEY, 0 otherwise. */
|
||||||
|
|
||||||
int
|
int
|
||||||
hash_table_exists (struct hash_table *ht, const void *key)
|
hash_table_contains (struct hash_table *ht, const void *key)
|
||||||
{
|
{
|
||||||
return find_mapping (ht, key) != NULL;
|
return find_mapping (ht, key) != NULL;
|
||||||
}
|
}
|
||||||
@ -450,7 +450,13 @@ hash_table_count (struct hash_table *ht)
|
|||||||
return ht->count;
|
return ht->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Support for hash tables whose keys are strings. */
|
/* Functions from this point onward are meant for convenience and
|
||||||
|
don't strictly belong to this file. However, this is as good a
|
||||||
|
place for them as any. */
|
||||||
|
|
||||||
|
/* ========
|
||||||
|
Support for hash tables whose keys are strings.
|
||||||
|
======== */
|
||||||
|
|
||||||
/* 31 bit hash function. Taken from Gnome's glib, modified to use
|
/* 31 bit hash function. Taken from Gnome's glib, modified to use
|
||||||
standard C types.
|
standard C types.
|
||||||
@ -471,6 +477,60 @@ string_hash (const void *key)
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Frontend for strcmp usable for hash tables. */
|
||||||
|
|
||||||
|
int
|
||||||
|
string_cmp (const void *s1, const void *s2)
|
||||||
|
{
|
||||||
|
return !strcmp ((const char *)s1, (const char *)s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return a hash table of initial size INITIAL_SIZE suitable to use
|
||||||
|
strings as keys. */
|
||||||
|
|
||||||
|
struct hash_table *
|
||||||
|
make_string_hash_table (int initial_size)
|
||||||
|
{
|
||||||
|
return hash_table_new (initial_size, string_hash, string_cmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========
|
||||||
|
Support for hash tables whose keys are strings, but which are
|
||||||
|
compared case-insensitively.
|
||||||
|
======== */
|
||||||
|
|
||||||
|
/* Like string_hash, but produce the same hash regardless of the case. */
|
||||||
|
|
||||||
|
static unsigned long
|
||||||
|
string_hash_nocase (const void *key)
|
||||||
|
{
|
||||||
|
const char *p = key;
|
||||||
|
unsigned int h = TOLOWER (*p);
|
||||||
|
|
||||||
|
if (h)
|
||||||
|
for (p += 1; *p != '\0'; p++)
|
||||||
|
h = (h << 5) - h + TOLOWER (*p);
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Like string_cmp, but doing case-insensitive compareison. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
string_cmp_nocase (const void *s1, const void *s2)
|
||||||
|
{
|
||||||
|
return !strcasecmp ((const char *)s1, (const char *)s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Like make_string_hash_table, but uses string_hash_nocase and
|
||||||
|
string_cmp_nocase. */
|
||||||
|
|
||||||
|
struct hash_table *
|
||||||
|
make_nocase_string_hash_table (int initial_size)
|
||||||
|
{
|
||||||
|
return hash_table_new (initial_size, string_hash_nocase, string_cmp_nocase);
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* If I ever need it: hashing of integers. */
|
/* If I ever need it: hashing of integers. */
|
||||||
|
|
||||||
@ -488,22 +548,6 @@ inthash (unsigned int key)
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
|
||||||
string_cmp (const void *s1, const void *s2)
|
|
||||||
{
|
|
||||||
return !strcmp ((const char *)s1, (const char *)s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return a hash table of initial size INITIAL_SIZE suitable to use
|
|
||||||
strings as keys. */
|
|
||||||
|
|
||||||
struct hash_table *
|
|
||||||
make_string_hash_table (int initial_size)
|
|
||||||
{
|
|
||||||
return hash_table_new (initial_size, string_hash, string_cmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef STANDALONE
|
#ifdef STANDALONE
|
||||||
|
|
||||||
@ -537,7 +581,7 @@ main (void)
|
|||||||
if (len <= 1)
|
if (len <= 1)
|
||||||
continue;
|
continue;
|
||||||
line[--len] = '\0';
|
line[--len] = '\0';
|
||||||
if (!hash_table_exists (ht, line))
|
if (!hash_table_contains (ht, line))
|
||||||
hash_table_put (ht, strdup (line), "here I am!");
|
hash_table_put (ht, strdup (line), "here I am!");
|
||||||
#if 1
|
#if 1
|
||||||
if (len % 5 == 0)
|
if (len % 5 == 0)
|
||||||
|
@ -40,7 +40,7 @@ void hash_table_destroy PARAMS ((struct hash_table *));
|
|||||||
void *hash_table_get PARAMS ((struct hash_table *, const void *));
|
void *hash_table_get PARAMS ((struct hash_table *, const void *));
|
||||||
int hash_table_get_pair PARAMS ((struct hash_table *, const void *,
|
int hash_table_get_pair PARAMS ((struct hash_table *, const void *,
|
||||||
void *, void *));
|
void *, void *));
|
||||||
int hash_table_exists PARAMS ((struct hash_table *, const void *));
|
int hash_table_contains PARAMS ((struct hash_table *, const void *));
|
||||||
|
|
||||||
void hash_table_put PARAMS ((struct hash_table *, const void *, void *));
|
void hash_table_put PARAMS ((struct hash_table *, const void *, void *));
|
||||||
int hash_table_remove PARAMS ((struct hash_table *, const void *));
|
int hash_table_remove PARAMS ((struct hash_table *, const void *));
|
||||||
@ -54,3 +54,4 @@ int hash_table_count PARAMS ((struct hash_table *));
|
|||||||
unsigned long string_hash PARAMS ((const void *));
|
unsigned long string_hash PARAMS ((const void *));
|
||||||
int string_cmp PARAMS ((const void *, const void *));
|
int string_cmp PARAMS ((const void *, const void *));
|
||||||
struct hash_table *make_string_hash_table PARAMS ((int));
|
struct hash_table *make_string_hash_table PARAMS ((int));
|
||||||
|
struct hash_table *make_nocase_string_hash_table PARAMS ((int));
|
||||||
|
@ -221,7 +221,7 @@ realhost (const char *host)
|
|||||||
char *master_name;
|
char *master_name;
|
||||||
|
|
||||||
DEBUGP (("Checking for %s in host_name_address_map.\n", host));
|
DEBUGP (("Checking for %s in host_name_address_map.\n", host));
|
||||||
if (hash_table_exists (host_name_address_map, host))
|
if (hash_table_contains (host_name_address_map, host))
|
||||||
{
|
{
|
||||||
DEBUGP (("Found; %s was already used, by that name.\n", host));
|
DEBUGP (("Found; %s was already used, by that name.\n", host));
|
||||||
return xstrdup_lower (host);
|
return xstrdup_lower (host);
|
||||||
|
@ -192,6 +192,7 @@ HTTP options:\n\
|
|||||||
--referer=URL include `Referer: URL\' header in HTTP request.\n\
|
--referer=URL include `Referer: URL\' header in HTTP request.\n\
|
||||||
-s, --save-headers save the HTTP headers to file.\n\
|
-s, --save-headers save the HTTP headers to file.\n\
|
||||||
-U, --user-agent=AGENT identify as AGENT instead of Wget/VERSION.\n\
|
-U, --user-agent=AGENT identify as AGENT instead of Wget/VERSION.\n\
|
||||||
|
--no-http-keep-alive disable HTTP keep-alive (persistent connections).\n\
|
||||||
--cookies=off don't use cookies.\n\
|
--cookies=off don't use cookies.\n\
|
||||||
--load-cookies=FILE load cookies from FILE before session.\n\
|
--load-cookies=FILE load cookies from FILE before session.\n\
|
||||||
--save-cookies=FILE save cookies to FILE after session.\n\
|
--save-cookies=FILE save cookies to FILE after session.\n\
|
||||||
|
@ -270,7 +270,7 @@ recursive_retrieve (const char *file, const char *this_url)
|
|||||||
/* inl is set if the URL we are working on (constr) is stored in
|
/* inl is set if the URL we are working on (constr) is stored in
|
||||||
undesirable_urls. Using it is crucial to avoid unnecessary
|
undesirable_urls. Using it is crucial to avoid unnecessary
|
||||||
repeated continuous hits to the hash table. */
|
repeated continuous hits to the hash table. */
|
||||||
inl = string_set_exists (undesirable_urls, constr);
|
inl = string_set_contains (undesirable_urls, constr);
|
||||||
|
|
||||||
/* If it is FTP, and FTP is not followed, chuck it out. */
|
/* If it is FTP, and FTP is not followed, chuck it out. */
|
||||||
if (!inl)
|
if (!inl)
|
||||||
|
@ -476,7 +476,7 @@ retrieve_url (const char *origurl, char **file, char **newloc,
|
|||||||
|
|
||||||
/* The new location is OK. Let's check for redirection cycle by
|
/* The new location is OK. Let's check for redirection cycle by
|
||||||
peeking through the history of redirections. */
|
peeking through the history of redirections. */
|
||||||
if (string_set_exists (redirections, newloc_struct->url))
|
if (string_set_contains (redirections, newloc_struct->url))
|
||||||
{
|
{
|
||||||
logprintf (LOG_NOTQUIET, _("%s: Redirection cycle detected.\n"),
|
logprintf (LOG_NOTQUIET, _("%s: Redirection cycle detected.\n"),
|
||||||
mynewloc);
|
mynewloc);
|
||||||
|
23
src/utils.c
23
src/utils.c
@ -1206,7 +1206,7 @@ string_set_add (struct hash_table *ht, const char *s)
|
|||||||
/* First check whether the set element already exists. If it does,
|
/* First check whether the set element already exists. If it does,
|
||||||
do nothing so that we don't have to free() the old element and
|
do nothing so that we don't have to free() the old element and
|
||||||
then strdup() a new one. */
|
then strdup() a new one. */
|
||||||
if (hash_table_exists (ht, s))
|
if (hash_table_contains (ht, s))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* We use "1" as value. It provides us a useful and clear arbitrary
|
/* We use "1" as value. It provides us a useful and clear arbitrary
|
||||||
@ -1216,12 +1216,12 @@ string_set_add (struct hash_table *ht, const char *s)
|
|||||||
hash_table_put (ht, xstrdup (s), "1");
|
hash_table_put (ht, xstrdup (s), "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Synonym for hash_table_exists... */
|
/* Synonym for hash_table_contains... */
|
||||||
|
|
||||||
int
|
int
|
||||||
string_set_exists (struct hash_table *ht, const char *s)
|
string_set_contains (struct hash_table *ht, const char *s)
|
||||||
{
|
{
|
||||||
return hash_table_exists (ht, s);
|
return hash_table_contains (ht, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1316,7 +1316,7 @@ legible (long l)
|
|||||||
bytes are sufficient. Using more might be a good idea.
|
bytes are sufficient. Using more might be a good idea.
|
||||||
|
|
||||||
This function does not go through the hoops that long_to_string
|
This function does not go through the hoops that long_to_string
|
||||||
goes to because it doesn't need to be fast. (It's called perhaps
|
goes to because it doesn't aspire to be fast. (It's called perhaps
|
||||||
once in a Wget run.) */
|
once in a Wget run.) */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1359,7 +1359,10 @@ numdigit (long a)
|
|||||||
{
|
{
|
||||||
int res = 1;
|
int res = 1;
|
||||||
if (a < 0)
|
if (a < 0)
|
||||||
|
{
|
||||||
a = -a;
|
a = -a;
|
||||||
|
++res;
|
||||||
|
}
|
||||||
while ((a /= 10) != 0)
|
while ((a /= 10) != 0)
|
||||||
++res;
|
++res;
|
||||||
return res;
|
return res;
|
||||||
@ -1379,7 +1382,7 @@ numdigit (long a)
|
|||||||
#define DIGITS_9(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_8 ((figure) / 10)
|
#define DIGITS_9(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_8 ((figure) / 10)
|
||||||
#define DIGITS_10(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_9 ((figure) / 10)
|
#define DIGITS_10(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_9 ((figure) / 10)
|
||||||
|
|
||||||
/* DIGITS_<11-20> are only used on 64-bit machines. */
|
/* DIGITS_<11-20> are only used on machines with 64-bit longs. */
|
||||||
|
|
||||||
#define DIGITS_11(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_10 ((figure) / 10)
|
#define DIGITS_11(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_10 ((figure) / 10)
|
||||||
#define DIGITS_12(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_11 ((figure) / 10)
|
#define DIGITS_12(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_11 ((figure) / 10)
|
||||||
@ -1400,9 +1403,9 @@ numdigit (long a)
|
|||||||
slow compared to this function.
|
slow compared to this function.
|
||||||
|
|
||||||
BUFFER should accept as many bytes as you expect the number to take
|
BUFFER should accept as many bytes as you expect the number to take
|
||||||
up. On 64-bit machines, the maximum needed size is 24 bytes. That
|
up. On machines with 64-bit longs the maximum needed size is 24
|
||||||
includes all the digits, as well as the `-' sign for negative
|
bytes. That includes the worst-case digits, the optional `-' sign,
|
||||||
numbers and the trailing \0. */
|
and the trailing \0. */
|
||||||
|
|
||||||
void
|
void
|
||||||
long_to_string (char *buffer, long number)
|
long_to_string (char *buffer, long number)
|
||||||
@ -1516,7 +1519,7 @@ struct wget_timer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Allocate a timer. It is not legal to do anything with a freshly
|
/* Allocate a timer. It is not legal to do anything with a freshly
|
||||||
allocated timer, except call wtimer_reset(). */
|
allocated timer, except call wtimer_reset() or wtimer_delete(). */
|
||||||
|
|
||||||
struct wget_timer *
|
struct wget_timer *
|
||||||
wtimer_allocate (void)
|
wtimer_allocate (void)
|
||||||
|
@ -81,7 +81,7 @@ int slist_contains PARAMS ((slist *, const char *));
|
|||||||
void slist_free PARAMS ((slist *));
|
void slist_free PARAMS ((slist *));
|
||||||
|
|
||||||
void string_set_add PARAMS ((struct hash_table *, const char *));
|
void string_set_add PARAMS ((struct hash_table *, const char *));
|
||||||
int string_set_exists PARAMS ((struct hash_table *, const char *));
|
int string_set_contains PARAMS ((struct hash_table *, const char *));
|
||||||
void string_set_free PARAMS ((struct hash_table *));
|
void string_set_free PARAMS ((struct hash_table *));
|
||||||
void free_keys_and_values PARAMS ((struct hash_table *));
|
void free_keys_and_values PARAMS ((struct hash_table *));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user