/* xmalloc, xrealloc and xstrdup exit the program if there is not
enough memory. xstrdup also implements strdup on systems that do
- not have it. */
+ not have it. xfree is provided to make leak-tracking easier.
+ Currently it's a no-op. */
+
void *
xmalloc (size_t size)
{
return res;
}
+void
+xfree (void *ptr)
+{
+ free (ptr);
+}
+
void *
xrealloc (void *obj, size_t size)
{
return filename;
else
{
- free (filename);
+ xfree (filename);
return NULL;
}
}
}
if (length == 0 || ferror (fp))
{
- free (line);
+ xfree (line);
return NULL;
}
if (length + 1 < bufsize)
lose:
if (!inhibit_close)
close (fd);
- free (fm->content);
- free (fm);
+ xfree (fm->content);
+ xfree (fm);
return NULL;
}
/* Release the resources held by FM. Specifically, this calls
- munmap() or free() on fm->content, depending whether mmap or
+ munmap() or xfree() on fm->content, depending whether mmap or
malloc/read were used to read in the file. It also frees the
memory needed to hold the FM structure itself. */
else
#endif
{
- free (fm->content);
+ xfree (fm->content);
}
- free (fm);
+ xfree (fm);
}
\f
/* Free the pointers in a NULL-terminated vector of pointers, then
{
char **p = vec;
while (*p)
- free (*p++);
- free (vec);
+ xfree (*p++);
+ xfree (vec);
}
}
if (!*v2)
{
/* To avoid j == 0 */
- free (v2);
+ xfree (v2);
return v1;
}
/* Count v1. */
/* Reallocate v1. */
v1 = (char **)xrealloc (v1, (i + j + 1) * sizeof (char **));
memcpy (v1 + i, v2, (j + 1) * sizeof (char *));
- free (v2);
+ xfree (v2);
return v1;
}
This used to also be used for searching, but now we have hash
tables for that. */
-/* Append an element to the list. */
+/* It's a shame that these simple things like linked lists and hash
+ tables (see hash.c) need to be implemented over and over again. It
+ would be nice to be able to use the routines from glib -- see
+ www.gtk.org for details. However, that would make Wget depend on
+ glib, and I want to avoid dependencies to external libraries for
+ reasons of convenience and portability (I suspect Wget is more
+ portable than anything ever written for Gnome). */
+
+/* Append an element to the list. If the list has a huge number of
+ elements, this can get slow because it has to find the list's
+ ending. If you think you have to call slist_append in a loop,
+ think about calling slist_prepend() followed by slist_nreverse(). */
+
slist *
slist_append (slist *l, const char *s)
{
return beg;
}
+/* Prepend S to the list. Unlike slist_append(), this is O(1). */
+
+slist *
+slist_prepend (slist *l, const char *s)
+{
+ slist *newel = (slist *)xmalloc (sizeof (slist));
+ newel->string = xstrdup (s);
+ newel->next = l;
+ return newel;
+}
+
+/* Destructively reverse L. */
+
+slist *
+slist_nreverse (slist *l)
+{
+ slist *prev = NULL;
+ while (l)
+ {
+ slist *next = l->next;
+ l->next = prev;
+ prev = l;
+ l = next;
+ }
+ return prev;
+}
+
/* Is there a specific entry in the list? */
int
slist_contains (slist *l, const char *s)
void
slist_free (slist *l)
{
- slist *n;
-
while (l)
{
- n = l->next;
- free (l->string);
- free (l);
+ slist *n = l->next;
+ xfree (l->string);
+ xfree (l);
l = n;
}
}
void
string_set_add (struct hash_table *ht, const char *s)
{
+ /* 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
+ then strdup() a new one. */
+ if (hash_table_exists (ht, s))
+ return;
+
/* We use "1" as value. It provides us a useful and clear arbitrary
value, and it consumes no memory -- the pointers to the same
- string "1" will be shared by all the key-value pairs in the hash
- table. */
+ string "1" will be shared by all the key-value pairs in all `set'
+ hash tables. */
hash_table_put (ht, xstrdup (s), "1");
}
+/* Synonym for hash_table_exists... */
+
int
string_set_exists (struct hash_table *ht, const char *s)
{
static int
string_set_free_mapper (void *key, void *value_ignored, void *arg_ignored)
{
- free (key);
+ xfree (key);
return 0;
}
static int
free_keys_and_values_mapper (void *key, void *value, void *arg_ignored)
{
- free (key);
- free (value);
+ xfree (key);
+ xfree (value);
return 0;
}
*p = '\0';
#endif /* (SIZEOF_LONG == 4) || (SIZEOF_LONG == 8) */
}
+\f
+/* This should probably be at a better place, but it doesn't really
+ fit into html-parse.c. */
+
+/* The function returns the pointer to the malloc-ed quoted version of
+ string s. It will recognize and quote numeric and special graphic
+ entities, as per RFC1866:
+
+ `&' -> `&'
+ `<' -> `<'
+ `>' -> `>'
+ `"' -> `"'
+ SP -> ` '
+
+ No other entities are recognized or replaced. */
+char *
+html_quote_string (const char *s)
+{
+ const char *b = s;
+ char *p, *res;
+ int i;
+
+ /* Pass through the string, and count the new size. */
+ for (i = 0; *s; s++, i++)
+ {
+ if (*s == '&')
+ i += 4; /* `amp;' */
+ else if (*s == '<' || *s == '>')
+ i += 3; /* `lt;' and `gt;' */
+ else if (*s == '\"')
+ i += 5; /* `quot;' */
+ else if (*s == ' ')
+ i += 4; /* #32; */
+ }
+ res = (char *)xmalloc (i + 1);
+ s = b;
+ for (p = res; *s; s++)
+ {
+ switch (*s)
+ {
+ case '&':
+ *p++ = '&';
+ *p++ = 'a';
+ *p++ = 'm';
+ *p++ = 'p';
+ *p++ = ';';
+ break;
+ case '<': case '>':
+ *p++ = '&';
+ *p++ = (*s == '<' ? 'l' : 'g');
+ *p++ = 't';
+ *p++ = ';';
+ break;
+ case '\"':
+ *p++ = '&';
+ *p++ = 'q';
+ *p++ = 'u';
+ *p++ = 'o';
+ *p++ = 't';
+ *p++ = ';';
+ break;
+ case ' ':
+ *p++ = '&';
+ *p++ = '#';
+ *p++ = '3';
+ *p++ = '2';
+ *p++ = ';';
+ break;
+ default:
+ *p++ = *s;
+ }
+ }
+ *p = '\0';
+ return res;
+}