+2005-04-07 Hrvoje Niksic <hniksic@xemacs.org>
+
+ * ptimer.c: New file. Move the "wtimer" functions from utils.c to
+ this file and rename them to ptimer_.
+
2005-04-07 Hrvoje Niksic <hniksic@xemacs.org>
* host.c (NO_ADDRESS): Define NO_ADDRESS only after the system
OBJ = $(ALLOCA) cmpt$o connect$o convert$o cookies$o \
ftp$o ftp-basic$o ftp-ls$o $(OPIE_OBJ) $(GETOPT_OBJ) hash$o \
host$o html-parse$o html-url$o http$o $(NTLM_OBJ) init$o \
- log$o main$o $(MD5_OBJ) netrc$o progress$o recur$o \
+ log$o main$o $(MD5_OBJ) netrc$o progress$o ptimer$o recur$o \
res$o retr$o safe-ctype$o snprintf$o $(SSL_OBJ) url$o \
utils$o version$o xmalloc$o
#include "recur.h"
#include "utils.h"
#include "hash.h"
+#include "ptimer.h"
static struct hash_table *dl_file_url_map;
struct hash_table *dl_url_file_map;
double secs;
int file_count = 0;
- struct wget_timer *timer = wtimer_new ();
+ struct ptimer *timer = ptimer_new ();
int cnt;
char **file_array;
free_urlpos (urls);
}
- wtimer_update (timer);
- secs = wtimer_read (timer) / 1000;
- wtimer_delete (timer);
+ secs = ptimer_measure (timer) / 1000;
+ ptimer_destroy (timer);
logprintf (LOG_VERBOSE, _("Converted %d files in %.*f seconds.\n"),
file_count, secs < 10 ? 3 : 1, secs);
}
string_set_add (downloaded_html_set, file);
}
-/* Cleanup the data structures associated with recursive retrieving
- (the variables above). */
+static void downloaded_files_free PARAMS ((void));
+
+/* Cleanup the data structures associated with this file. */
+
void
convert_cleanup (void)
{
}
if (downloaded_html_set)
string_set_free (downloaded_html_set);
+ downloaded_files_free ();
}
\f
/* Book-keeping code for downloaded files that enables extension
return 0;
}
-void
+static void
downloaded_files_free (void)
{
if (downloaded_files_hash)
downloaded_files_hash = NULL;
}
}
+\f
+/* 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;
+}
void convert_all_links PARAMS ((void));
void convert_cleanup PARAMS ((void));
+char *html_quote_string PARAMS ((const char *));
+
#endif /* CONVERT_H */
#include "utils.h"
#include "ftp.h"
#include "url.h"
+#include "convert.h" /* for html_quote_string prototype */
extern FILE *output_stream;
#include "progress.h"
#include "recur.h" /* for INFINITE_RECURSION */
#include "convert.h" /* for convert_cleanup */
+#include "res.h" /* for res_cleanup */
#ifndef errno
extern int errno;
}
\f
void cleanup_html_url PARAMS ((void));
-void res_cleanup PARAMS ((void));
-void downloaded_files_free PARAMS ((void));
void http_cleanup PARAMS ((void));
res_cleanup ();
http_cleanup ();
cleanup_html_url ();
- downloaded_files_free ();
host_cleanup ();
log_cleanup ();
--- /dev/null
+/* Portable timers.
+ Copyright (C) 2005 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. */
+
+/* This file implements "portable timers" (ptimers), objects that
+ measure elapsed time using the primitives most appropriate for the
+ underlying operating system. The entry points are:
+
+ ptimer_new -- creates a timer.
+ ptimer_reset -- resets the timer's elapsed time to zero.
+ ptimer_measure -- measure and return the time elapsed since
+ creation or last reset.
+ ptimer_read -- reads the last measured elapsed value.
+ ptimer_destroy -- destroy the timer.
+ ptimer_granularity -- returns the approximate granularity of the timers.
+
+ Timers operate in milliseconds, but return floating point values
+ that can be more precise. For example, to measure the time it
+ takes to run a loop, you can use something like:
+
+ ptimer *tmr = ptimer_new ();
+ while (...)
+ ... loop ...
+ double msecs = ptimer_measure ();
+ printf ("The loop took %.2f ms\n", msecs); */
+
+#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>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <assert.h>
+
+#include "wget.h"
+#include "ptimer.h"
+
+#ifndef errno
+extern int errno;
+#endif
+
+/* Depending on the OS and availability of gettimeofday(), one and
+ only one of PTIMER_WINDOWS, PTIMER_GETTIMEOFDAY, or PTIMER_TIME will
+ be defined.
+
+ Virtually all modern Unix systems will define PTIMER_GETTIMEOFDAY;
+ Windows will use PTIMER_WINDOWS. PTIMER_TIME is a catch-all method
+ for non-Windows systems without gettimeofday, such as DOS or really
+ old Unix-like systems. */
+
+#undef PTIMER_POSIX
+#undef PTIMER_GETTIMEOFDAY
+#undef PTIMER_TIME
+#undef PTIMER_WINDOWS
+
+#ifdef WINDOWS
+# define PTIMER_WINDOWS /* use Windows timers */
+#else
+# if _POSIX_TIMERS > 0
+# define PTIMER_POSIX /* use POSIX timers (clock_gettime) */
+# else
+# ifdef HAVE_GETTIMEOFDAY
+# define PTIMER_GETTIMEOFDAY /* use gettimeofday */
+# else
+# define PTIMER_TIME
+# endif
+# endif
+#endif
+
+/* The type ptimer_system_time holds system time. */
+
+#ifdef PTIMER_POSIX
+typedef struct timespec ptimer_system_time;
+#endif
+
+#ifdef PTIMER_GETTIMEOFDAY
+typedef struct timeval ptimer_system_time;
+#endif
+
+#ifdef PTIMER_TIME
+typedef time_t ptimer_system_time;
+#endif
+
+#ifdef PTIMER_WINDOWS
+typedef union {
+ DWORD lores; /* In case GetTickCount is used */
+ LARGE_INTEGER hires; /* In case high-resolution timer is used */
+} ptimer_system_time;
+#endif
+
+struct ptimer {
+ /* Whether the start time has been set. */
+ int initialized;
+
+ /* The starting point in time which, subtracted from the current
+ time, yields elapsed time. */
+ ptimer_system_time start;
+
+ /* The most recent elapsed time, calculated by ptimer_measure().
+ Measured in milliseconds. */
+ double elapsed_last;
+
+ /* Approximately, the time elapsed between the true start of the
+ measurement and the time represented by START. */
+ double elapsed_pre_start;
+};
+
+#ifdef PTIMER_WINDOWS
+/* Whether high-resolution timers are used. Set by ptimer_initialize_once
+ the first time ptimer_allocate is called. */
+static int windows_hires_timers;
+
+/* Frequency of high-resolution timers -- number of updates per
+ millisecond. Calculated the first time ptimer_allocate is called
+ provided that high-resolution timers are available. */
+static double windows_hires_msfreq;
+
+/* The first time a timer is created, determine whether to use
+ high-resolution timers. */
+
+static void
+ptimer_init (void)
+{
+ LARGE_INTEGER freq;
+ freq.QuadPart = 0;
+ QueryPerformanceFrequency (&freq);
+ if (freq.QuadPart != 0)
+ {
+ windows_hires_timers = 1;
+ windows_hires_msfreq = (double) freq.QuadPart / 1000.0;
+ }
+}
+#define PTIMER_INIT_DEFINED
+#endif /* PTIMER_WINDOWS */
+
+#ifdef PTIMER_POSIX
+
+/* clock_id to use for POSIX clocks. This tries to use
+ CLOCK_MONOTONIC where available, CLOCK_REALTIME otherwise. */
+static int posix_clock_id;
+
+/* Resolution of the clock, in milliseconds. */
+static double posix_resolution;
+
+/* Check whether the monotonic clock is available, and retrieve POSIX
+ timer resolution. */
+
+static void
+ptimer_init (void)
+{
+ struct timespec res;
+
+#if _POSIX_MONOTONIC_CLOCK > 0
+ if (sysconf (_SC_MONOTONIC_CLOCK) > 0)
+ posix_clock_id = CLOCK_MONOTONIC;
+ else
+#endif
+ posix_clock_id = CLOCK_REALTIME;
+
+ if (clock_getres (posix_clock_id, &res) < 0)
+ {
+ logprintf (LOG_NOTQUIET, _("Cannot read clock resolution: %s\n"),
+ strerror (errno));
+ /* Assume 1 ms resolution */
+ res.tv_sec = 0;
+ res.tv_nsec = 1000000;
+ }
+
+ posix_resolution = res.tv_sec * 1000.0 + res.tv_nsec / 1000000.0;
+ /* Guard against clock_getres reporting 0 resolution; after all, it
+ can be used for division. */
+ if (posix_resolution == 0)
+ posix_resolution = 1;
+}
+#define PTIMER_INIT_DEFINED
+#endif
+
+/* Allocate a timer. Calling ptimer_read on the timer will return
+ zero. It is not legal to call ptimer_measure with a freshly
+ allocated timer -- use ptimer_reset first. */
+
+struct ptimer *
+ptimer_allocate (void)
+{
+ struct ptimer *wt;
+
+#ifdef PTIMER_INIT_DEFINED
+ static int init_done;
+ if (!init_done)
+ {
+ init_done = 1;
+ ptimer_init ();
+ }
+#endif
+
+ wt = xnew0 (struct ptimer);
+ return wt;
+}
+
+/* Allocate a new timer and reset it. Return the new timer. */
+
+struct ptimer *
+ptimer_new (void)
+{
+ struct ptimer *wt = ptimer_allocate ();
+ ptimer_reset (wt);
+ return wt;
+}
+
+/* Free the resources associated with the timer. Its further use is
+ prohibited. */
+
+void
+ptimer_destroy (struct ptimer *wt)
+{
+ xfree (wt);
+}
+
+/* Store system time to PST. */
+
+static void
+ptimer_sys_set (ptimer_system_time *pst)
+{
+#ifdef PTIMER_POSIX
+ clock_gettime (posix_clock_id, pst);
+#endif
+
+#ifdef PTIMER_GETTIMEOFDAY
+ gettimeofday (pst, NULL);
+#endif
+
+#ifdef PTIMER_TIME
+ time (pst);
+#endif
+
+#ifdef PTIMER_WINDOWS
+ if (windows_hires_timers)
+ {
+ QueryPerformanceCounter (&pst->hires);
+ }
+ else
+ {
+ /* Where hires counters are not available, use GetTickCount rather
+ GetSystemTime, because it is unaffected by clock skew and simpler
+ to use. Note that overflows don't affect us because we never use
+ absolute values of the ticker, only the differences. */
+ pst->lores = GetTickCount ();
+ }
+#endif
+}
+
+/* Reset timer WT. This establishes the starting point from which
+ ptimer_read() will return the number of elapsed milliseconds.
+ It is allowed to reset a previously used timer. */
+
+void
+ptimer_reset (struct ptimer *wt)
+{
+ /* Set the start time to the current time. */
+ ptimer_sys_set (&wt->start);
+ wt->elapsed_last = 0;
+ wt->elapsed_pre_start = 0;
+ wt->initialized = 1;
+}
+
+static double
+ptimer_diff (ptimer_system_time *pst1, ptimer_system_time *pst2)
+{
+#ifdef PTIMER_POSIX
+ return ((pst1->tv_sec - pst2->tv_sec) * 1000.0
+ + (pst1->tv_nsec - pst2->tv_nsec) / 1000000.0);
+#endif
+
+#ifdef PTIMER_GETTIMEOFDAY
+ return ((pst1->tv_sec - pst2->tv_sec) * 1000.0
+ + (pst1->tv_usec - pst2->tv_usec) / 1000.0);
+#endif
+
+#ifdef PTIMER_TIME
+ return 1000 * (*pst1 - *pst2);
+#endif
+
+#ifdef WINDOWS
+ if (using_hires_timers)
+ return (pst1->hires.QuadPart - pst2->hires.QuadPart) / windows_hires_msfreq;
+ else
+ return pst1->lores - pst2->lores;
+#endif
+}
+
+/* Measure the elapsed time since timer creation/reset and return it
+ to the caller. The value remains stored for further reads by
+ ptimer_read.
+
+ This function causes the timer to call gettimeofday (or time(),
+ etc.) to update its idea of current time. To get the elapsed
+ interval in milliseconds, use ptimer_read.
+
+ This function handles clock skew, i.e. time that moves backwards is
+ ignored. */
+
+double
+ptimer_measure (struct ptimer *wt)
+{
+ ptimer_system_time now;
+ double elapsed;
+
+ assert (wt->initialized != 0);
+
+ ptimer_sys_set (&now);
+ elapsed = wt->elapsed_pre_start + ptimer_diff (&now, &wt->start);
+
+ /* Ideally we'd just return the difference between NOW and
+ wt->start. However, the system timer can be set back, and we
+ could return a value smaller than when we were last called, even
+ a negative value. Both of these would confuse the callers, which
+ expect us to return monotonically nondecreasing values.
+
+ Therefore: if ELAPSED is smaller than its previous known value,
+ we reset wt->start to the current time and effectively start
+ measuring from this point. But since we don't want the elapsed
+ value to start from zero, we set elapsed_pre_start to the last
+ elapsed time and increment all future calculations by that
+ amount.
+
+ This cannot happen with Windows and CLOCK_MONOTONIC timers, but
+ the check is not expensive. */
+
+ if (elapsed < wt->elapsed_last)
+ {
+ wt->start = now;
+ wt->elapsed_pre_start = wt->elapsed_last;
+ elapsed = wt->elapsed_last;
+ }
+
+ wt->elapsed_last = elapsed;
+ return elapsed;
+}
+
+/* Return the elapsed time in milliseconds between the last call to
+ ptimer_reset and the last call to ptimer_update. */
+
+double
+ptimer_read (const struct ptimer *wt)
+{
+ return wt->elapsed_last;
+}
+
+/* Return the assessed granularity of the timer implementation, in
+ milliseconds. This is used by code that tries to substitute a
+ better value for timers that have returned zero. */
+
+double
+ptimer_granularity (void)
+{
+#ifdef PTIMER_POSIX
+ /* POSIX timers give us a way to measure granularity. */
+ assert (posix_resolution != 0);
+ return posix_resolution;
+#endif
+
+#ifdef PTIMER_GETTIMEOFDAY
+ /* Granularity of gettimeofday varies wildly between architectures.
+ However, it appears that on modern machines it tends to be better
+ than 1ms. Assume 100 usecs. */
+ return 0.1;
+#endif
+
+#ifdef PTIMER_TIME
+ return 1000;
+#endif
+
+#ifdef PTIMER_WINDOWS
+ if (windows_hires_timers)
+ return 1.0 / windows_hires_msfreq;
+ else
+ return 10; /* according to MSDN */
+#endif
+}
--- /dev/null
+/* Declarations for ptimer.c.
+ Copyright (C) 2005 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 PTIMER_H
+#define PTIMER_H
+
+struct ptimer; /* forward declaration; all struct
+ members are private */
+
+struct ptimer *ptimer_allocate PARAMS ((void));
+struct ptimer *ptimer_new PARAMS ((void));
+void ptimer_destroy PARAMS ((struct ptimer *));
+
+void ptimer_reset PARAMS ((struct ptimer *));
+double ptimer_measure PARAMS ((struct ptimer *));
+double ptimer_read PARAMS ((const struct ptimer *));
+
+double ptimer_granularity PARAMS ((void));
+
+#endif /* PTIMER_H */
#include "connect.h"
#include "hash.h"
#include "convert.h"
+#include "ptimer.h"
#ifdef HAVE_SSL
# include "gen_sslfunc.h" /* for ssl_iread */
is the timer that started at the beginning of download. */
static void
-limit_bandwidth (wgint bytes, struct wget_timer *timer)
+limit_bandwidth (wgint bytes, struct ptimer *timer)
{
- double delta_t = wtimer_read (timer) - limit_data.chunk_start;
+ double delta_t = ptimer_read (timer) - limit_data.chunk_start;
double expected;
limit_data.chunk_bytes += bytes;
slp, number_to_static_string (limit_data.chunk_bytes),
limit_data.sleep_adjust));
- t0 = wtimer_read (timer);
+ t0 = ptimer_read (timer);
xsleep (slp / 1000);
- wtimer_update (timer);
- t1 = wtimer_read (timer);
+ t1 = ptimer_measure (timer);
/* Due to scheduling, we probably slept slightly longer (or
shorter) than desired. Calculate the difference between the
}
limit_data.chunk_bytes = 0;
- limit_data.chunk_start = wtimer_read (timer);
+ limit_data.chunk_start = ptimer_read (timer);
}
#ifndef MIN
static char dlbuf[16384];
int dlbufsize = sizeof (dlbuf);
- struct wget_timer *timer = NULL;
+ struct ptimer *timer = NULL;
double last_successful_read_tm = 0;
/* The progress gauge, set according to the user preferences. */
the timer. */
if (progress || opt.limit_rate || elapsed)
{
- timer = wtimer_new ();
+ timer = ptimer_new ();
last_successful_read_tm = 0;
}
if (opt.read_timeout)
{
double waittm;
- waittm = (wtimer_read (timer) - last_successful_read_tm) / 1000;
+ waittm = (ptimer_read (timer) - last_successful_read_tm) / 1000;
if (waittm + tmout > opt.read_timeout)
{
/* Don't let total idle time exceed read timeout. */
if (progress || opt.limit_rate)
{
- wtimer_update (timer);
+ ptimer_measure (timer);
if (ret > 0)
- last_successful_read_tm = wtimer_read (timer);
+ last_successful_read_tm = ptimer_read (timer);
}
if (ret > 0)
limit_bandwidth (ret, timer);
if (progress)
- progress_update (progress, ret, wtimer_read (timer));
+ progress_update (progress, ret, ptimer_read (timer));
#ifdef WINDOWS
if (toread > 0 && !opt.quiet)
ws_percenttitle (100.0 *
out:
if (progress)
- progress_finish (progress, wtimer_read (timer));
+ progress_finish (progress, ptimer_read (timer));
if (elapsed)
- *elapsed = wtimer_read (timer);
+ *elapsed = ptimer_read (timer);
if (timer)
- wtimer_delete (timer);
+ ptimer_destroy (timer);
if (qtyread)
*qtyread += sum_read;
if (msecs == 0)
/* If elapsed time is exactly zero, it means we're under the
- granularity of the timer. This often happens on systems that
- use time() for the timer. */
- msecs = wtimer_granularity ();
+ granularity of the timer. This can easily happen on systems
+ that use time() for the timer. Since the interval lies between
+ 0 and the timer's granularity, assume half the granularity. */
+ msecs = ptimer_granularity () / 2.0;
- dlrate = (double)1000 * bytes / msecs;
+ dlrate = 1000.0 * bytes / msecs;
if (dlrate < 1024.0)
*units = 0;
else if (dlrate < 1024.0 * 1024.0)
return buf;
}
\f
-/* Support for timers. */
-
-#undef TIMER_WINDOWS
-#undef TIMER_GETTIMEOFDAY
-#undef TIMER_TIME
-
-/* Depending on the OS and availability of gettimeofday(), one and
- only one of the above constants will be defined. Virtually all
- modern Unix systems will define TIMER_GETTIMEOFDAY; Windows will
- use TIMER_WINDOWS. TIMER_TIME is a catch-all method for
- non-Windows systems without gettimeofday. */
-
-#ifdef WINDOWS
-# define TIMER_WINDOWS
-#else /* not WINDOWS */
-# ifdef HAVE_GETTIMEOFDAY
-# define TIMER_GETTIMEOFDAY
-# else
-# define TIMER_TIME
-# endif
-#endif /* not WINDOWS */
-
-#ifdef TIMER_GETTIMEOFDAY
-typedef struct timeval wget_sys_time;
-#endif
-
-#ifdef TIMER_TIME
-typedef time_t wget_sys_time;
-#endif
-
-#ifdef TIMER_WINDOWS
-typedef union {
- DWORD lores; /* In case GetTickCount is used */
- LARGE_INTEGER hires; /* In case high-resolution timer is used */
-} wget_sys_time;
-#endif
-
-struct wget_timer {
- /* Whether the start time has been initialized. */
- int initialized;
-
- /* The starting point in time which, subtracted from the current
- time, yields elapsed time. */
- wget_sys_time start;
-
- /* The most recent elapsed time, calculated by wtimer_update().
- Measured in milliseconds. */
- double elapsed_last;
-
- /* Approximately, the time elapsed between the true start of the
- measurement and the time represented by START. */
- double elapsed_pre_start;
-};
-
-#ifdef TIMER_WINDOWS
-
-/* Whether high-resolution timers are used. Set by wtimer_initialize_once
- the first time wtimer_allocate is called. */
-static int using_hires_timers;
-
-/* Frequency of high-resolution timers -- number of updates per
- millisecond. Calculated the first time wtimer_allocate is called
- provided that high-resolution timers are available. */
-static double hires_millisec_freq;
-
-/* The first time a timer is created, determine whether to use
- high-resolution timers. */
-
-static void
-wtimer_initialize_once (void)
-{
- static int init_done;
- if (!init_done)
- {
- LARGE_INTEGER freq;
- init_done = 1;
- freq.QuadPart = 0;
- QueryPerformanceFrequency (&freq);
- if (freq.QuadPart != 0)
- {
- using_hires_timers = 1;
- hires_millisec_freq = (double) freq.QuadPart / 1000.0;
- }
- }
-}
-#endif /* TIMER_WINDOWS */
-
-/* Allocate a timer. Calling wtimer_read on the timer will return
- zero. It is not legal to call wtimer_update with a freshly
- allocated timer -- use wtimer_reset first. */
-
-struct wget_timer *
-wtimer_allocate (void)
-{
- struct wget_timer *wt = xnew (struct wget_timer);
- xzero (*wt);
-
-#ifdef TIMER_WINDOWS
- wtimer_initialize_once ();
-#endif
-
- return wt;
-}
-
-/* Allocate a new timer and reset it. Return the new timer. */
-
-struct wget_timer *
-wtimer_new (void)
-{
- struct wget_timer *wt = wtimer_allocate ();
- wtimer_reset (wt);
- return wt;
-}
-
-/* Free the resources associated with the timer. Its further use is
- prohibited. */
-
-void
-wtimer_delete (struct wget_timer *wt)
-{
- xfree (wt);
-}
-
-/* Store system time to WST. */
-
-static void
-wtimer_sys_set (wget_sys_time *wst)
-{
-#ifdef TIMER_GETTIMEOFDAY
- gettimeofday (wst, NULL);
-#endif
-
-#ifdef TIMER_TIME
- time (wst);
-#endif
-
-#ifdef TIMER_WINDOWS
- if (using_hires_timers)
- {
- QueryPerformanceCounter (&wst->hires);
- }
- else
- {
- /* Where hires counters are not available, use GetTickCount rather
- GetSystemTime, because it is unaffected by clock skew and simpler
- to use. Note that overflows don't affect us because we never use
- absolute values of the ticker, only the differences. */
- wst->lores = GetTickCount ();
- }
-#endif
-}
-
-/* Reset timer WT. This establishes the starting point from which
- wtimer_read() will return the number of elapsed milliseconds.
- It is allowed to reset a previously used timer. */
-
-void
-wtimer_reset (struct wget_timer *wt)
-{
- /* Set the start time to the current time. */
- wtimer_sys_set (&wt->start);
- wt->elapsed_last = 0;
- wt->elapsed_pre_start = 0;
- wt->initialized = 1;
-}
-
-static double
-wtimer_sys_diff (wget_sys_time *wst1, wget_sys_time *wst2)
-{
-#ifdef TIMER_GETTIMEOFDAY
- return ((double)(wst1->tv_sec - wst2->tv_sec) * 1000
- + (double)(wst1->tv_usec - wst2->tv_usec) / 1000);
-#endif
-
-#ifdef TIMER_TIME
- return 1000 * (*wst1 - *wst2);
-#endif
-
-#ifdef WINDOWS
- if (using_hires_timers)
- return (wst1->hires.QuadPart - wst2->hires.QuadPart) / hires_millisec_freq;
- else
- return wst1->lores - wst2->lores;
-#endif
-}
-
-/* Update the timer's elapsed interval. This function causes the
- timer to call gettimeofday (or time(), etc.) to update its idea of
- current time. To get the elapsed interval in milliseconds, use
- wtimer_read.
-
- This function handles clock skew, i.e. time that moves backwards is
- ignored. */
-
-void
-wtimer_update (struct wget_timer *wt)
-{
- wget_sys_time now;
- double elapsed;
-
- assert (wt->initialized != 0);
-
- wtimer_sys_set (&now);
- elapsed = wt->elapsed_pre_start + wtimer_sys_diff (&now, &wt->start);
-
- /* Ideally we'd just return the difference between NOW and
- wt->start. However, the system timer can be set back, and we
- could return a value smaller than when we were last called, even
- a negative value. Both of these would confuse the callers, which
- expect us to return monotonically nondecreasing values.
-
- Therefore: if ELAPSED is smaller than its previous known value,
- we reset wt->start to the current time and effectively start
- measuring from this point. But since we don't want the elapsed
- value to start from zero, we set elapsed_pre_start to the last
- elapsed time and increment all future calculations by that
- amount. */
-
- if (elapsed < wt->elapsed_last)
- {
- wt->start = now;
- wt->elapsed_pre_start = wt->elapsed_last;
- elapsed = wt->elapsed_last;
- }
-
- wt->elapsed_last = elapsed;
-}
-
-/* Return the elapsed time in milliseconds between the last call to
- wtimer_reset and the last call to wtimer_update.
-
- A typical use of the timer interface would be:
-
- struct wtimer *timer = wtimer_new ();
- ... do something that takes a while ...
- wtimer_update ();
- double msecs = wtimer_read (); */
-
-double
-wtimer_read (const struct wget_timer *wt)
-{
- return wt->elapsed_last;
-}
-
-/* Return the assessed granularity of the timer implementation, in
- milliseconds. This is used by code that tries to substitute a
- better value for timers that have returned zero. */
-
-double
-wtimer_granularity (void)
-{
-#ifdef TIMER_GETTIMEOFDAY
- /* Granularity of gettimeofday varies wildly between architectures.
- However, it appears that on modern machines it tends to be better
- than 1ms. Assume 100 usecs. (Perhaps the configure process
- could actually measure this?) */
- return 0.1;
-#endif
-
-#ifdef TIMER_TIME
- return 1000;
-#endif
-
-#ifdef TIMER_WINDOWS
- if (using_hires_timers)
- return 1.0 / hires_millisec_freq;
- else
- return 10; /* according to MSDN */
-#endif
-}
-\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;
-}
-
/* Determine the width of the terminal we're running on. If that's
not possible, return 0. */
{
NEXT_BASE64_CHAR (c, p);
if (!c)
- return -1; /* premature EOF while dcoding base64 */
+ return -1; /* premature EOF while decoding base64 */
if (c != '=')
return -1; /* padding `=' expected but not found */
continue;
/* Process fourth byte of a quadruplet. */
NEXT_BASE64_CHAR (c, p);
if (!c)
- return -1; /* premature EOF while dcoding base64 */
+ return -1; /* premature EOF while decoding base64 */
if (c == '=')
continue;
#define HYPHENP(x) (*(x) == '-' && !*((x) + 1))
-struct wget_timer;
-
char *time_str PARAMS ((time_t *));
char *datetime_str PARAMS ((time_t *));
char *number_to_string PARAMS ((char *, wgint));
char *number_to_static_string PARAMS ((wgint));
-struct wget_timer *wtimer_allocate PARAMS ((void));
-struct wget_timer *wtimer_new PARAMS ((void));
-void wtimer_delete PARAMS ((struct wget_timer *));
-void wtimer_reset PARAMS ((struct wget_timer *));
-void wtimer_update PARAMS ((struct wget_timer *));
-double wtimer_read PARAMS ((const struct wget_timer *));
-double wtimer_granularity PARAMS ((void));
-
-char *html_quote_string PARAMS ((const char *));
-
int determine_screen_width PARAMS ((void));
int random_number PARAMS ((int));
double random_float PARAMS ((void));