+
+ return p;
+}
+
+#undef ONE_DIGIT
+#undef ONE_DIGIT_ADVANCE
+
+#undef DIGITS_1
+#undef DIGITS_2
+#undef DIGITS_3
+#undef DIGITS_4
+#undef DIGITS_5
+#undef DIGITS_6
+#undef DIGITS_7
+#undef DIGITS_8
+#undef DIGITS_9
+#undef DIGITS_10
+#undef DIGITS_11
+#undef DIGITS_12
+#undef DIGITS_13
+#undef DIGITS_14
+#undef DIGITS_15
+#undef DIGITS_16
+#undef DIGITS_17
+#undef DIGITS_18
+#undef DIGITS_19
+\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.
+
+ #### Perhaps we should also support ftime(), which exists on old
+ BSD 4.2-influenced systems? (It also existed under MS DOS Borland
+ C, if memory serves me.) */
+
+#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 ULARGE_INTEGER wget_sys_time;
+#endif
+
+struct wget_timer {
+ /* 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_elapsed().
+ 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;
+};
+
+/* Allocate a timer. It is not legal to do anything with a freshly
+ allocated timer, except call wtimer_reset() or wtimer_delete(). */
+
+struct wget_timer *
+wtimer_allocate (void)
+{
+ struct wget_timer *wt =
+ (struct wget_timer *)xmalloc (sizeof (struct wget_timer));
+ 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
+ /* We use GetSystemTime to get the elapsed time. MSDN warns that
+ system clock adjustments can skew the output of GetSystemTime
+ when used as a timer and gives preference to GetTickCount and
+ high-resolution timers. But GetTickCount can overflow, and hires
+ timers are typically used for profiling, not for regular time
+ measurement. Since we handle clock skew anyway, we just use
+ GetSystemTime. */
+ FILETIME ft;
+ SYSTEMTIME st;
+ GetSystemTime (&st);
+
+ /* As recommended by MSDN, we convert SYSTEMTIME to FILETIME, copy
+ FILETIME to ULARGE_INTEGER, and use regular 64-bit integer
+ arithmetic on that. */
+ SystemTimeToFileTime (&st, &ft);
+ wst->HighPart = ft.dwHighDateTime;
+ wst->LowPart = ft.dwLowDateTime;
+#endif
+}
+
+/* Reset timer WT. This establishes the starting point from which
+ wtimer_elapsed() 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;
+}
+
+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
+ return (double)(wst1->QuadPart - wst2->QuadPart) / 10000;
+#endif
+}
+
+/* Return the number of milliseconds elapsed since the timer was last
+ reset. It is allowed to call this function more than once to get
+ increasingly higher elapsed values. These timers handle clock
+ skew. */
+
+double
+wtimer_elapsed (struct wget_timer *wt)
+{
+ wget_sys_time now;
+ double elapsed;
+
+ 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 elapsed;
+}
+
+/* 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
+ /* This is clear. */
+ return 1000;
+#endif
+
+#ifdef TIMER_WINDOWS
+ /* According to MSDN, GetSystemTime returns a broken-down time
+ structure the smallest member of which are milliseconds. */
+ return 1;
+#endif