+2003-10-31 Hrvoje Niksic <hniksic@xemacs.org>
+
+ * wget.h: Move declarations of malloc and logging code to
+ xmalloc.h and log.h respectively to unclutter this file.
+ (STRDUP_ALLOCA): Made it side-effect free.
+
+ * xmalloc.h: New files. Define macros xnew, xnew0, xnew_array,
+ and xnew0_array.
+
+ * xmalloc.c: New file. Move the xmalloc routines here.
+
2003-10-31 Hrvoje Niksic <hniksic@xemacs.org>
* connect.c (sockaddr_set_data): Remove the broken code that
headers$o host$o html-parse$o html-url$o http$o init$o \
log$o main$o $(MD5_OBJ) netrc$o progress$o rbuf$o recur$o \
res$o retr$o safe-ctype$o snprintf$o $(SSL_OBJ) url$o \
- utils$o version$o
+ utils$o version$o xmalloc$o
.SUFFIXES:
.SUFFIXES: .c .o ._c ._o
url$o: wget.h sysdep.h options.h safe-ctype.h utils.h url.h host.h hash.h
utils$o: wget.h sysdep.h options.h safe-ctype.h utils.h hash.h
version$o:
+xmalloc$o: wget.h xmalloc.h
includes. */
struct gen_md5_context;
+#define MD5_HASHLEN 16
+
#define ALLOCA_MD5_CONTEXT(var_name) \
gen_md5_context *var_name = \
(gen_md5_context *) alloca (gen_md5_context_size ())
{
char* last_period_in_local_filename = strrchr(*hs->local_file, '.');
- if (last_period_in_local_filename == NULL ||
- !(strcasecmp(last_period_in_local_filename, ".htm") == EQ ||
- strcasecmp(last_period_in_local_filename, ".html") == EQ))
+ if (last_period_in_local_filename == NULL
+ || !(0 == strcasecmp (last_period_in_local_filename, ".htm")
+ || 0 == strcasecmp (last_period_in_local_filename, ".html")))
{
size_t local_filename_len = strlen(*hs->local_file);
#include "wget.h"
#include "utils.h"
+#include "log.h"
#ifndef errno
extern int errno;
--- /dev/null
+/* Declarations for log.c.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Wget.
+
+GNU Wget is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+GNU Wget is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Wget; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In addition, as a special exception, the Free Software Foundation
+gives permission to link the code of its release of Wget with the
+OpenSSL project's "OpenSSL" library (or with modified versions of it
+that use the same license as the "OpenSSL" library), and distribute
+the linked executables. You must obey the GNU General Public License
+in all respects for all of the code used other than "OpenSSL". If you
+modify this file, you may extend this exception to your version of the
+file, but you are not obligated to do so. If you do not wish to do
+so, delete this exception statement from your version. */
+
+#ifndef LOG_H
+#define LOG_H
+
+/* Make gcc check for the format of logmsg() and debug_logmsg(). */
+#ifdef __GNUC__
+# define GCC_FORMAT_ATTR(a, b) __attribute__ ((format (printf, a, b)))
+#else /* not __GNUC__ */
+# define GCC_FORMAT_ATTR(a, b)
+#endif /* not __GNUC__ */
+
+enum log_options { LOG_VERBOSE, LOG_NOTQUIET, LOG_NONVERBOSE, LOG_ALWAYS };
+
+#ifdef HAVE_STDARG_H
+void logprintf PARAMS ((enum log_options, const char *, ...))
+ GCC_FORMAT_ATTR (2, 3);
+void debug_logprintf PARAMS ((const char *, ...)) GCC_FORMAT_ATTR (1, 2);
+#else /* not HAVE_STDARG_H */
+void logprintf ();
+void debug_logprintf ();
+#endif /* not HAVE_STDARG_H */
+void logputs PARAMS ((enum log_options, const char *));
+void logflush PARAMS ((void));
+void log_set_flush PARAMS ((int));
+int log_set_save_context PARAMS ((int));
+
+#endif /* LOG_H */
return 1;
}
+#define MIN(p,q) (((p) <= (q)) ? (p) : (q))
+
/* Flush RBUF's buffer to WHERE. Flush MAXSIZE bytes at most.
Returns the number of bytes actually copied. If the buffer is
empty, 0 is returned. */
return 0;
else
{
- int howmuch = MINVAL (rbuf->buffer_left, maxsize);
+ int howmuch = MIN (rbuf->buffer_left, maxsize);
if (where)
memcpy (where, rbuf->buffer_pos, howmuch);
-/* Various functions of utilitarian nature.
- Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001
- Free Software Foundation, Inc.
+/* Various utility functions.
+ Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of GNU Wget.
extern int errno;
#endif
-/* This section implements several wrappers around the basic
- allocation routines. This is done for two reasons: first, so that
- the callers of these functions need not consistently check for
- errors. If there is not enough virtual memory for running Wget,
- something is seriously wrong, and Wget exits with an appropriate
- error message.
-
- The second reason why these are useful is that, if DEBUG_MALLOC is
- defined, they also provide a handy (if crude) malloc debugging
- interface that checks memory leaks. */
-
-/* Croak the fatal memory error and bail out with non-zero exit
- status. */
-static void
-memfatal (const char *what)
-{
- /* Make sure we don't try to store part of the log line, and thus
- call malloc. */
- log_set_save_context (0);
- logprintf (LOG_ALWAYS, _("%s: %s: Not enough memory.\n"), exec_name, what);
- exit (1);
-}
-
-/* These functions end with _real because they need to be
- distinguished from the debugging functions, and from the macros.
- Explanation follows:
-
- If memory debugging is not turned on, wget.h defines these:
-
- #define xmalloc xmalloc_real
- #define xrealloc xrealloc_real
- #define xstrdup xstrdup_real
- #define xfree free
-
- In case of memory debugging, the definitions are a bit more
- complex, because we want to provide more information, *and* we want
- to call the debugging code. (The former is the reason why xmalloc
- and friends need to be macros in the first place.) Then it looks
- like this:
-
- #define xmalloc(a) xmalloc_debug (a, __FILE__, __LINE__)
- #define xfree(a) xfree_debug (a, __FILE__, __LINE__)
- #define xrealloc(a, b) xrealloc_debug (a, b, __FILE__, __LINE__)
- #define xstrdup(a) xstrdup_debug (a, __FILE__, __LINE__)
-
- Each of the *_debug function does its magic and calls the real one. */
-
-#ifdef DEBUG_MALLOC
-# define STATIC_IF_DEBUG static
-#else
-# define STATIC_IF_DEBUG
-#endif
-
-STATIC_IF_DEBUG void *
-xmalloc_real (size_t size)
-{
- void *ptr = malloc (size);
- if (!ptr)
- memfatal ("malloc");
- return ptr;
-}
-
-STATIC_IF_DEBUG void *
-xrealloc_real (void *ptr, size_t newsize)
-{
- void *newptr;
-
- /* Not all Un*xes have the feature of realloc() that calling it with
- a NULL-pointer is the same as malloc(), but it is easy to
- simulate. */
- if (ptr)
- newptr = realloc (ptr, newsize);
- else
- newptr = malloc (newsize);
- if (!newptr)
- memfatal ("realloc");
- return newptr;
-}
-
-STATIC_IF_DEBUG char *
-xstrdup_real (const char *s)
-{
- char *copy;
-
-#ifndef HAVE_STRDUP
- int l = strlen (s);
- copy = malloc (l + 1);
- if (!copy)
- memfatal ("strdup");
- memcpy (copy, s, l + 1);
-#else /* HAVE_STRDUP */
- copy = strdup (s);
- if (!copy)
- memfatal ("strdup");
-#endif /* HAVE_STRDUP */
-
- return copy;
-}
-
-#ifdef DEBUG_MALLOC
-
-/* Crude home-grown routines for debugging some malloc-related
- problems. Featured:
-
- * Counting the number of malloc and free invocations, and reporting
- the "balance", i.e. how many times more malloc was called than it
- was the case with free.
-
- * Making malloc store its entry into a simple array and free remove
- stuff from that array. At the end, print the pointers which have
- not been freed, along with the source file and the line number.
- This also has the side-effect of detecting freeing memory that
- was never allocated.
-
- Note that this kind of memory leak checking strongly depends on
- every malloc() being followed by a free(), even if the program is
- about to finish. Wget is careful to free the data structure it
- allocated in init.c. */
-
-static int malloc_count, free_count;
-
-static struct {
- char *ptr;
- const char *file;
- int line;
-} malloc_debug[100000];
-
-/* Both register_ptr and unregister_ptr take O(n) operations to run,
- which can be a real problem. It would be nice to use a hash table
- for malloc_debug, but the functions in hash.c are not suitable
- because they can call malloc() themselves. Maybe it would work if
- the hash table were preallocated to a huge size, and if we set the
- rehash threshold to 1.0. */
-
-/* Register PTR in malloc_debug. Abort if this is not possible
- (presumably due to the number of current allocations exceeding the
- size of malloc_debug.) */
-
-static void
-register_ptr (void *ptr, const char *file, int line)
-{
- int i;
- for (i = 0; i < countof (malloc_debug); i++)
- if (malloc_debug[i].ptr == NULL)
- {
- malloc_debug[i].ptr = ptr;
- malloc_debug[i].file = file;
- malloc_debug[i].line = line;
- return;
- }
- abort ();
-}
-
-/* Unregister PTR from malloc_debug. Abort if PTR is not present in
- malloc_debug. (This catches calling free() with a bogus pointer.) */
-
-static void
-unregister_ptr (void *ptr)
-{
- int i;
- for (i = 0; i < countof (malloc_debug); i++)
- if (malloc_debug[i].ptr == ptr)
- {
- malloc_debug[i].ptr = NULL;
- return;
- }
- abort ();
-}
-
-/* Print the malloc debug stats that can be gathered from the above
- information. Currently this is the count of mallocs, frees, the
- difference between the two, and the dump of the contents of
- malloc_debug. The last part are the memory leaks. */
-
-void
-print_malloc_debug_stats (void)
-{
- int i;
- printf ("\nMalloc: %d\nFree: %d\nBalance: %d\n\n",
- malloc_count, free_count, malloc_count - free_count);
- for (i = 0; i < countof (malloc_debug); i++)
- if (malloc_debug[i].ptr != NULL)
- printf ("0x%08ld: %s:%d\n", (long)malloc_debug[i].ptr,
- malloc_debug[i].file, malloc_debug[i].line);
-}
-
-void *
-xmalloc_debug (size_t size, const char *source_file, int source_line)
-{
- void *ptr = xmalloc_real (size);
- ++malloc_count;
- register_ptr (ptr, source_file, source_line);
- return ptr;
-}
-
-void
-xfree_debug (void *ptr, const char *source_file, int source_line)
-{
- assert (ptr != NULL);
- ++free_count;
- unregister_ptr (ptr);
- free (ptr);
-}
-
-void *
-xrealloc_debug (void *ptr, size_t newsize, const char *source_file, int source_line)
-{
- void *newptr = xrealloc_real (ptr, newsize);
- if (!ptr)
- {
- ++malloc_count;
- register_ptr (newptr, source_file, source_line);
- }
- else if (newptr != ptr)
- {
- unregister_ptr (ptr);
- register_ptr (newptr, source_file, source_line);
- }
- return newptr;
-}
-
-char *
-xstrdup_debug (const char *s, const char *source_file, int source_line)
-{
- char *copy = xstrdup_real (s);
- ++malloc_count;
- register_ptr (copy, source_file, source_line);
- return copy;
-}
-
-#endif /* DEBUG_MALLOC */
-\f
/* Utility function: like xstrdup(), but also lowercases S. */
char *
int mmap_p;
};
+#define HYPHENP(x) (*(x) == '-' && !*((x) + 1))
+
struct wget_timer;
char *time_str PARAMS ((time_t *));
# define DEBUGP(x) DO_NOTHING
#endif /* not ENABLE_DEBUG */
-/* Make gcc check for the format of logmsg() and debug_logmsg(). */
-#ifdef __GNUC__
-# define GCC_FORMAT_ATTR(a, b) __attribute__ ((format (printf, a, b)))
-#else /* not __GNUC__ */
-# define GCC_FORMAT_ATTR(a, b)
-#endif /* not __GNUC__ */
-
-/* These are from log.c, but they are used everywhere, so we declare
- them here. */
-enum log_options { LOG_VERBOSE, LOG_NOTQUIET, LOG_NONVERBOSE, LOG_ALWAYS };
-
-#ifdef HAVE_STDARG_H
-void logprintf PARAMS ((enum log_options, const char *, ...))
- GCC_FORMAT_ATTR (2, 3);
-void debug_logprintf PARAMS ((const char *, ...)) GCC_FORMAT_ATTR (1, 2);
-#else /* not HAVE_STDARG_H */
-void logprintf ();
-void debug_logprintf ();
-#endif /* not HAVE_STDARG_H */
-void logputs PARAMS ((enum log_options, const char *));
-void logflush PARAMS ((void));
-void log_set_flush PARAMS ((int));
-int log_set_save_context PARAMS ((int));
-
-/* Defined in `utils.c', but used literally everywhere. */
-#ifndef DEBUG_MALLOC
-
-#define xmalloc xmalloc_real
-#define xrealloc xrealloc_real
-#define xstrdup xstrdup_real
-#define xfree free
-
-void *xmalloc_real PARAMS ((size_t));
-void *xrealloc_real PARAMS ((void *, size_t));
-char *xstrdup_real PARAMS ((const char *));
-
-#else /* DEBUG_MALLOC */
-
-#define xmalloc(s) xmalloc_debug (s, __FILE__, __LINE__)
-#define xfree(p) xfree_debug (p, __FILE__, __LINE__)
-#define xrealloc(p, s) xrealloc_debug (p, s, __FILE__, __LINE__)
-#define xstrdup(p) xstrdup_debug (p, __FILE__, __LINE__)
-
-void *xmalloc_debug PARAMS ((size_t, const char *, int));
-void xfree_debug PARAMS ((void *, const char *, int));
-void *xrealloc_debug PARAMS ((void *, size_t, const char *, int));
-char *xstrdup_debug PARAMS ((const char *, const char *, int));
-
-#endif /* DEBUG_MALLOC */
+/* Everything uses this, so include them here directly. */
+#include "xmalloc.h"
+
+/* Likewise for logging functions. */
+#include "log.h"
/* #### Find a better place for this. */
/* The log file to which Wget writes to after HUP. */
#define DEFAULT_LOGFILE "wget-log"
-
-#define MD5_HASHLEN 16
\f
/* Useful macros used across the code: */
-/* Is the string a hpyhen-only? */
-#define HYPHENP(x) (*(x) == '-' && !*((x) + 1))
+/* The number of elements in an array. For example:
+ static char a[] = "foo"; -- countof(a) == 4 (for terminating \0)
+ int a[5] = {1, 2}; -- countof(a) == 5
+ char *a[] = { -- countof(a) == 3
+ "foo", "bar", "baz"
+ }; */
+#define countof(array) (sizeof (array) / sizeof ((array)[0]))
-/* The smaller value of the two. */
-#define MINVAL(x, y) ((x) < (y) ? (x) : (y))
+/* Zero out a value. */
+#define xzero(x) memset (&(x), '\0', sizeof (x))
/* Convert an ASCII hex digit to the corresponding number between 0
and 15. X should be a hexadecimal digit that satisfies isxdigit;
otherwise, the result is undefined. */
-#define XDIGIT_TO_NUM(x) ((x) < 'A' ? (x) - '0' : TOUPPER (x) - 'A' + 10)
-
-/* Convert a sequence of ASCII hex digits X and Y to a number betewen
- 0 and 255. Uses XDIGIT_TO_NUM for conversion of individual
- digits. */
+#define XDIGIT_TO_NUM(h) ((h) < 'A' ? (h) - '0' : TOUPPER (h) - 'A' + 10)
#define X2DIGITS_TO_NUM(h1, h2) ((XDIGIT_TO_NUM (h1) << 4) + XDIGIT_TO_NUM (h2))
/* The reverse of the above: convert a number in the [0, 16) range to
- its ASCII representation in hex. The A-F characters are in upper
- case. */
-#define XNUM_TO_DIGIT(x) ("0123456789ABCDEF"[x])
-
-/* Like XNUM_TO_DIGIT, but generates lower-case characters. */
-#define XNUM_TO_digit(x) ("0123456789abcdef"[x])
-
-/* Returns the number of elements in an array with fixed
- initialization. For example:
-
- static char a[] = "foo"; -- countof(a) == 4 (for terminating \0)
-
- int a[5] = {1, 2}; -- countof(a) == 5
-
- char *a[] = { -- countof(a) == 3
- "foo", "bar", "baz"
- }; */
-#define countof(array) (sizeof (array) / sizeof (*(array)))
-
-#define alloca_array(type, size) ((type *) alloca ((size) * sizeof (type)))
+ the ASCII representation of the corresponding hex digit. The `+ 0'
+ is so you don't accidentally use it as an lvalue. */
+#define XNUM_TO_DIGIT(x) ("0123456789ABCDEF"[x] + 0)
+#define XNUM_TO_digit(x) ("0123456789abcdef"[x] + 0)
/* Copy the data delimited with BEG and END to alloca-allocated
storage, and zero-terminate it. Arguments are evaluated only once,
#define STRDUP_ALLOCA(str) (strcpy ((char *)alloca (strlen (str) + 1), str))
This is because some compilers don't handle alloca() as argument to
- function correctly. Gcc under Intel has been reported to offend in
- this case. */
-
-#define STRDUP_ALLOCA(ptr, str) do { \
- (ptr) = (char *)alloca (strlen (str) + 1); \
- strcpy ((ptr), (str)); \
+ function correctly. Gcc on Intel platforms has been reported to
+ offend in this case. */
+
+#define STRDUP_ALLOCA(ptr, str) do { \
+ char **SA_dest = &(ptr); \
+ const char *SA_src = (str); \
+ *SA_dest = (char *)alloca (strlen (SA_src) + 1); \
+ strcpy (*SA_dest, SA_src); \
} while (0)
/* Generally useful if you want to avoid arbitrary size limits but
will realloc BASEVAR as necessary so that it can hold at least
NEEDED_SIZE objects. The reallocing is done by doubling, which
ensures constant amortized time per element. */
-#define DO_REALLOC(basevar, sizevar, needed_size, type) do \
-{ \
- /* Avoid side-effectualness. */ \
+#define DO_REALLOC(basevar, sizevar, needed_size, type) do { \
+ /* Avoid side effects by prefixing the local vars. */ \
long do_realloc_needed_size = (needed_size); \
long do_realloc_newsize = 0; \
while ((sizevar) < (do_realloc_needed_size)) { \
} while (0)
/* Free FOO if it is non-NULL. */
-#define FREE_MAYBE(foo) do { if (foo) xfree (foo); } while (0)
+#define FREE_MAYBE(foo) do { if (foo) xfree ((foo)); } while (0)
extern const char *exec_name;
\f
SSLERRCERTFILE,SSLERRCERTKEY,SSLERRCTXCREATE
} uerr_t;
+/* These are not used widely. They should either be removed or used
+ consistently. */
typedef unsigned char boolean;
#ifndef FALSE
-#define FALSE 0
+# define FALSE 0
#endif
#ifndef TRUE
-#define TRUE 1
+# define TRUE 1
#endif
-/* So we can say strcmp(a, b) == EQ rather than strcmp(a, b) == 0 or
- the really awful !strcmp(a, b). */
-#define EQ 0
-
-/* For most options, 0 means no limits, but with -p in the picture, that causes
- a problem on the maximum recursion depth variable. To retain backwards
- compatibility we allow users to consider "0" to be synonymous with "inf" for
- -l, but internally infinite recursion is specified by -1 and 0 means to only
- retrieve the requisites of a single document. */
+/* For most options, 0 means no limits, but with -p in the picture,
+ that causes a problem on the maximum recursion depth variable. To
+ retain backwards compatibility we allow users to consider "0" to be
+ synonymous with "inf" for -l, but internally infinite recursion is
+ specified by -1 and 0 means to only retrieve the requisites of a
+ single document. */
#define INFINITE_RECURSION -1
/* In case old systems don't have EAFNOSUPPORT, which we use below. */
--- /dev/null
+/* Wrappers around malloc and memory debugging support.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Wget.
+
+GNU Wget is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+GNU Wget is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Wget; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In addition, as a special exception, the Free Software Foundation
+gives permission to link the code of its release of Wget with the
+OpenSSL project's "OpenSSL" library (or with modified versions of it
+that use the same license as the "OpenSSL" library), and distribute
+the linked executables. You must obey the GNU General Public License
+in all respects for all of the code used other than "OpenSSL". If you
+modify this file, you may extend this exception to your version of the
+file, but you are not obligated to do so. If you do not wish to do
+so, delete this exception statement from your version. */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else /* not HAVE_STRING_H */
+# include <strings.h>
+#endif /* not HAVE_STRING_H */
+#include <sys/types.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "wget.h"
+#include "xmalloc.h"
+
+#ifndef errno
+extern int errno;
+#endif
+
+/* This file implements several wrappers around the basic allocation
+ routines. This is done for two reasons: first, so that the callers
+ of these functions need not check for errors, which is easy to
+ forget. If there is not enough virtual memory for running Wget,
+ something is seriously wrong, and Wget exits with an appropriate
+ error message.
+
+ The second reason why these are useful is that, if DEBUG_MALLOC is
+ defined, they also provide a handy (if crude) malloc debugging
+ interface that checks memory leaks. */
+
+/* Croak the fatal memory error and bail out with non-zero exit
+ status. */
+
+static void
+memfatal (const char *context, long size)
+{
+ /* Make sure we don't try to store part of the log line, and thus
+ call malloc. */
+ log_set_save_context (0);
+ logprintf (LOG_ALWAYS, _("%s: %s: Cannot allocate %ld bytes.\n"),
+ exec_name, context, size);
+ exit (1);
+}
+
+/* These functions end with _real because they need to be
+ distinguished from the debugging functions, and from the macros.
+ Explanation follows:
+
+ If memory debugging is not turned on, wget.h defines these:
+
+ #define xmalloc xmalloc_real
+ #define xmalloc0 xmalloc0_real
+ #define xrealloc xrealloc_real
+ #define xstrdup xstrdup_real
+ #define xfree free
+
+ In case of memory debugging, the definitions are a bit more
+ complex, because we want to provide more information, *and* we want
+ to call the debugging code. (The former is the reason why xmalloc
+ and friends need to be macros in the first place.) Then it looks
+ like this:
+
+ #define xmalloc(a) xmalloc_debug (a, __FILE__, __LINE__)
+ #define xmalloc0(a) xmalloc0_debug (a, __FILE__, __LINE__)
+ #define xfree(a) xfree_debug (a, __FILE__, __LINE__)
+ #define xrealloc(a, b) xrealloc_debug (a, b, __FILE__, __LINE__)
+ #define xstrdup(a) xstrdup_debug (a, __FILE__, __LINE__)
+
+ Each of the *_debug function does its magic and calls the real one. */
+
+#ifdef DEBUG_MALLOC
+# define STATIC_IF_DEBUG static
+#else
+# define STATIC_IF_DEBUG
+#endif
+
+STATIC_IF_DEBUG void *
+xmalloc_real (size_t size)
+{
+ void *ptr = malloc (size);
+ if (!ptr)
+ memfatal ("malloc", size);
+ return ptr;
+}
+
+STATIC_IF_DEBUG void *
+xmalloc0_real (size_t size)
+{
+ /* Using calloc can be faster than malloc+memset because some calloc
+ implementations know when they're dealing with zeroed-out memory
+ from the system and can avoid unnecessary memset. */
+ void *ptr = calloc (1, size);
+ if (!ptr)
+ memfatal ("calloc", size);
+ return ptr;
+}
+
+STATIC_IF_DEBUG void *
+xrealloc_real (void *ptr, size_t newsize)
+{
+ void *newptr;
+
+ /* Not all Un*xes have the feature of realloc() that calling it with
+ a NULL-pointer is the same as malloc(), but it is easy to
+ simulate. */
+ if (ptr)
+ newptr = realloc (ptr, newsize);
+ else
+ newptr = malloc (newsize);
+ if (!newptr)
+ memfatal ("realloc", newsize);
+ return newptr;
+}
+
+STATIC_IF_DEBUG char *
+xstrdup_real (const char *s)
+{
+ char *copy;
+
+#ifndef HAVE_STRDUP
+ int l = strlen (s);
+ copy = malloc (l + 1);
+ if (!copy)
+ memfatal ("strdup", l + 1);
+ memcpy (copy, s, l + 1);
+#else /* HAVE_STRDUP */
+ copy = strdup (s);
+ if (!copy)
+ memfatal ("strdup", 1 + strlen (s));
+#endif /* HAVE_STRDUP */
+
+ return copy;
+}
+
+#ifdef DEBUG_MALLOC
+
+/* Crude home-grown routines for debugging some malloc-related
+ problems. Featured:
+
+ * Counting the number of malloc and free invocations, and reporting
+ the "balance", i.e. how many times more malloc was called than it
+ was the case with free.
+
+ * Making malloc store its entry into a simple array and free remove
+ stuff from that array. At the end, print the pointers which have
+ not been freed, along with the source file and the line number.
+ This also has the side-effect of detecting freeing memory that
+ was never allocated.
+
+ Note that this kind of memory leak checking strongly depends on
+ every malloc() being followed by a free(), even if the program is
+ about to finish. Wget is careful to free the data structure it
+ allocated in init.c. */
+
+static int malloc_count, free_count;
+
+static struct {
+ char *ptr;
+ const char *file;
+ int line;
+} malloc_debug[100000];
+
+/* Both register_ptr and unregister_ptr take O(n) operations to run,
+ which can be a real problem. It would be nice to use a hash table
+ for malloc_debug, but the functions in hash.c are not suitable
+ because they can call malloc() themselves. Maybe it would work if
+ the hash table were preallocated to a huge size, and if we set the
+ rehash threshold to 1.0. */
+
+/* Register PTR in malloc_debug. Abort if this is not possible
+ (presumably due to the number of current allocations exceeding the
+ size of malloc_debug.) */
+
+static void
+register_ptr (void *ptr, const char *file, int line)
+{
+ int i;
+ for (i = 0; i < countof (malloc_debug); i++)
+ if (malloc_debug[i].ptr == NULL)
+ {
+ malloc_debug[i].ptr = ptr;
+ malloc_debug[i].file = file;
+ malloc_debug[i].line = line;
+ return;
+ }
+ abort ();
+}
+
+/* Unregister PTR from malloc_debug. Abort if PTR is not present in
+ malloc_debug. (This catches calling free() with a bogus pointer.) */
+
+static void
+unregister_ptr (void *ptr)
+{
+ int i;
+ for (i = 0; i < countof (malloc_debug); i++)
+ if (malloc_debug[i].ptr == ptr)
+ {
+ malloc_debug[i].ptr = NULL;
+ return;
+ }
+ abort ();
+}
+
+/* Print the malloc debug stats that can be gathered from the above
+ information. Currently this is the count of mallocs, frees, the
+ difference between the two, and the dump of the contents of
+ malloc_debug. The last part are the memory leaks. */
+
+void
+print_malloc_debug_stats (void)
+{
+ int i;
+ printf ("\nMalloc: %d\nFree: %d\nBalance: %d\n\n",
+ malloc_count, free_count, malloc_count - free_count);
+ for (i = 0; i < countof (malloc_debug); i++)
+ if (malloc_debug[i].ptr != NULL)
+ printf ("0x%08ld: %s:%d\n", (long)malloc_debug[i].ptr,
+ malloc_debug[i].file, malloc_debug[i].line);
+}
+
+void *
+xmalloc_debug (size_t size, const char *source_file, int source_line)
+{
+ void *ptr = xmalloc_real (size);
+ ++malloc_count;
+ register_ptr (ptr, source_file, source_line);
+ return ptr;
+}
+
+void *
+xmalloc0_debug (size_t size, const char *source_file, int source_line)
+{
+ void *ptr = xmalloc0_real (size);
+ ++malloc_count;
+ register_ptr (ptr, source_file, source_line);
+ return ptr;
+}
+
+void *
+xrealloc_debug (void *ptr, size_t newsize, const char *source_file, int source_line)
+{
+ void *newptr = xrealloc_real (ptr, newsize);
+ if (!ptr)
+ {
+ ++malloc_count;
+ register_ptr (newptr, source_file, source_line);
+ }
+ else if (newptr != ptr)
+ {
+ unregister_ptr (ptr);
+ register_ptr (newptr, source_file, source_line);
+ }
+ return newptr;
+}
+
+char *
+xstrdup_debug (const char *s, const char *source_file, int source_line)
+{
+ char *copy = xstrdup_real (s);
+ ++malloc_count;
+ register_ptr (copy, source_file, source_line);
+ return copy;
+}
+
+void
+xfree_debug (void *ptr, const char *source_file, int source_line)
+{
+ assert (ptr != NULL);
+ ++free_count;
+ unregister_ptr (ptr);
+ free (ptr);
+}
+
+#endif /* DEBUG_MALLOC */
--- /dev/null
+/* xmalloc.c declarations.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Wget.
+
+GNU Wget is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+GNU Wget is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Wget; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In addition, as a special exception, the Free Software Foundation
+gives permission to link the code of its release of Wget with the
+OpenSSL project's "OpenSSL" library (or with modified versions of it
+that use the same license as the "OpenSSL" library), and distribute
+the linked executables. You must obey the GNU General Public License
+in all respects for all of the code used other than "OpenSSL". If you
+modify this file, you may extend this exception to your version of the
+file, but you are not obligated to do so. If you do not wish to do
+so, delete this exception statement from your version. */
+
+#ifndef XMALLOC_H
+#define XMALLOC_H
+
+/* When DEBUG_MALLOC is not defined (which is normally the case), the
+ allocation functions directly map to *_real wrappers. In the
+ DEBUG_MALLOC mode, they also record the file and line where the
+ offending malloc/free/... was invoked. */
+
+#ifndef DEBUG_MALLOC
+
+#define xmalloc xmalloc_real
+#define xmalloc0 xmalloc0_real
+#define xrealloc xrealloc_real
+#define xstrdup xstrdup_real
+#define xfree free
+
+void *xmalloc_real PARAMS ((size_t));
+void *xmalloc0_real PARAMS ((size_t));
+void *xrealloc_real PARAMS ((void *, size_t));
+char *xstrdup_real PARAMS ((const char *));
+
+#else /* DEBUG_MALLOC */
+
+#define xmalloc(s) xmalloc_debug (s, __FILE__, __LINE__)
+#define xmalloc0(s) xmalloc0_debug (s, __FILE__, __LINE__)
+#define xfree(p) xfree_debug (p, __FILE__, __LINE__)
+#define xrealloc(p, s) xrealloc_debug (p, s, __FILE__, __LINE__)
+#define xstrdup(p) xstrdup_debug (p, __FILE__, __LINE__)
+
+void *xmalloc_debug PARAMS ((size_t, const char *, int));
+void *xmalloc0_debug PARAMS ((size_t, const char *, int));
+void xfree_debug PARAMS ((void *, const char *, int));
+void *xrealloc_debug PARAMS ((void *, size_t, const char *, int));
+char *xstrdup_debug PARAMS ((const char *, const char *, int));
+
+#endif /* DEBUG_MALLOC */
+
+/* Macros that interface to malloc, but know about type sizes, and
+ cast the result to the appropriate type. The casts are not
+ necessary in standard C, but Wget performs them anyway for the sake
+ of pre-standard environments and possibly C++. */
+
+#define xnew(type) ((type *) xmalloc (sizeof (type)))
+#define xnew0(type) ((type *) xmalloc0 (sizeof (type)))
+#define xnew_array(type, len) ((type *) xmalloc ((len) * sizeof (type)))
+#define xnew0_array(type, len) ((type *) xmalloc0 ((len) * sizeof (type)))
+
+#define alloca_array(type, size) ((type *) alloca ((size) * sizeof (type)))
+
+#endif /* XMALLOC_H */
SRC = cmpt.c safe-ctype.c convert.c connect.c host.c http.c netrc.c \
ftp-basic.c ftp.c ftp-ls.c ftp-opie.c getopt.c hash.c headers.c \
html-parse.c html-url.c progress.c retr.c recur.c res.c url.c cookies.c \
- init.c utils.c main.c version.c mswindows.c gen-md5.c \
- gnu-md5.c rbuf.c log.c $(SSLSRC)
+ init.c utils.c main.c version.c xmalloc.c mswindows.c \
+ gen-md5.c gnu-md5.c rbuf.c log.c $(SSLSRC)
OBJ = cmpt$o safe-ctype$o convert$o connect$o host$o http$o netrc$o \
ftp-basic$o ftp$o ftp-ls$o ftp-opie$o getopt$o hash$o headers$o \
html-parse$o html-url$o progress$o retr$o recur$o res$o url$o cookies$o \
- init$o utils$o main$o version$o mswindows$o gen-md5$o gnu-md5$o\
- rbuf$o log$o $(SSLOBJ)
+ init$o utils$o main$o version$o xmalloc$o mswindows$o \
+ gen-md5$o gnu-md5$o rbuf$o log$o $(SSLOBJ)
.SUFFIXES: .c .obj
ftp-ls.obj ftp-opie.obj getopt.obj headers.obj host.obj html-parse.obj html-url.obj \
http.obj init.obj log.obj main.obj gnu-md5.obj netrc.obj rbuf.obj \
safe-ctype.obj hash.obj progress.obj gen-md5.obj cookies.obj \
- recur.obj res.obj retr.obj url.obj utils.obj version.obj mswindows.obj
+ recur.obj res.obj retr.obj url.obj utils.obj version.obj xmalloc.obj \
+ mswindows.obj
LIBDIR=$(MAKEDIR)\..\lib
$(LINK) @&&|
$(LFLAGS) -Tpe -ap -c +
$(LIBDIR)\c0x32.obj+
+cmpt.obj
+connect.obj+
convert.obj+
cookies.obj+
-hash.obj+
-safe-ctype.obj+
-version.obj+
-utils.obj+
-url.obj+
-retr.obj+
-res.obj+
-recur.obj+
-rbuf.obj+
-progress.obj+
-netrc.obj+
-mswindows.obj+
-gnu-md5.obj+
+ftp-basic.obj+
+ftp-ls.obj+
+ftp-opie.obj+
+ftp.obj+
gen-md5.obj+
-main.obj+
-log.obj+
-init.obj+
-http.obj+
+getopt.obj+
+gnu-md5.obj+
+hash.obj+
+headers.obj+
+host.obj+
html-parse.obj+
html-url.obj+
-host.obj+
-headers.obj+
-getopt.obj+
-ftp-opie.obj+
-ftp-ls.obj+
-ftp-basic.obj+
-ftp.obj+
-connect.obj+
-cmpt.obj
+http.obj+
+init.obj+
+log.obj+
+main.obj+
+mswindows.obj+
+netrc.obj+
+progress.obj+
+rbuf.obj+
+recur.obj+
+res.obj+
+retr.obj+
+safe-ctype.obj+
+url.obj+
+utils.obj+
+version.obj+
+xmalloc.obj+
$<,$*
$(LIBDIR)\import32.lib+
$(LIBDIR)\cw32.lib
ftp-ls${OBJ_EXT} ftp-opie${OBJ_EXT} getopt${OBJ_EXT} headers${OBJ_EXT} host${OBJ_EXT} html-parse${OBJ_EXT} html-url${OBJ_EXT} \
http${OBJ_EXT} init${OBJ_EXT} log${OBJ_EXT} main${OBJ_EXT} gnu-md5${OBJ_EXT} netrc${OBJ_EXT} rbuf${OBJ_EXT} \
safe-ctype${OBJ_EXT} hash${OBJ_EXT} progress${OBJ_EXT} gen-md5${OBJ_EXT} cookies${OBJ_EXT} \
- recur${OBJ_EXT} res${OBJ_EXT} retr${OBJ_EXT} url${OBJ_EXT} utils${OBJ_EXT} version${OBJ_EXT} mswindows${OBJ_EXT}
+ recur${OBJ_EXT} res${OBJ_EXT} retr${OBJ_EXT} url${OBJ_EXT} utils${OBJ_EXT} \
+ version${OBJ_EXT} xmalloc${OBJ_EXT} mswindows${OBJ_EXT}
ifdef SSL
## OPENSSL_PATH is the OpenSSL installed directory
* Douglas E. Wegscheid -- maintains configure.bat and various Windows
makefiles.
+
+* Herold Heiko -- numerous build reports and fixes.
+
+* Gisle Vanem -- many Windows-related improvements to the source and
+ the build system.
url$o: url.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h url.h host.h hash.h
utils$o: utils.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h hash.h
version$o: version.c
+xmalloc$o: wget.h xmalloc.h