From dfad2b94f5fa40db86bd11e475c310751efafe69 Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Fri, 3 Sep 2004 18:14:00 +0000 Subject: [PATCH] Some UN*Xes don't have any "strtou*" routine to convert a string to a 64-bit integer; use "g_ascii_strtoull()", and, in the configure script, check whether it's available in GLib (it's not in GLib 1.2[.x]) and, if not, supply the GLib 2.4.5 version of the routine. For G_MAXUINT32 and G_MAXUINT64, put a "U" at the end of the constant to explicitly flag it as unsigned. svn path=/trunk/; revision=11889 --- config.h.win32 | 3 - configure.in | 34 +++---- epan/Makefile.am | 8 +- epan/ftypes/ftype-integer.c | 10 +- epan/g_ascii_strtoull.c | 197 ++++++++++++++++++++++++++++++++++++ epan/g_ascii_strtoull.h | 15 +++ 6 files changed, 240 insertions(+), 27 deletions(-) create mode 100644 epan/g_ascii_strtoull.c create mode 100644 epan/g_ascii_strtoull.h diff --git a/config.h.win32 b/config.h.win32 index 339b29a59d..49b178bfe5 100644 --- a/config.h.win32 +++ b/config.h.win32 @@ -157,9 +157,6 @@ #endif /* _MSC_EXTENSIONS */ #endif /* PRIx64 */ -/* Define as a function that behaves like strtoull */ -#define strtoull g_ascii_strtoull - /* Define if you have the z library (-lz). */ @HAVE_LIBZ@ diff --git a/configure.in b/configure.in index 88a14ba9fb..c78a8dbd43 100644 --- a/configure.in +++ b/configure.in @@ -468,24 +468,6 @@ else ]) fi -AC_CHECK_FUNC(strtoull,, - [ - # - # No strtoull - do we have strtouq? - # - AC_CHECK_FUNC(strtouq, - [ - # - # Yes - define strtoull to be strtouq. - # - AC_DEFINE(strtoull, strtouq, - [Define as a function that behaves like strtoull]) - ], - [ - AC_MSG_ERROR([This platform has neither strtoull nor strtouq.]) - ]) - ]) - AC_SUBST(ethereal_bin) AC_SUBST(ethereal_man) @@ -1009,6 +991,22 @@ fi AC_SUBST(MKSTEMP_C) AC_SUBST(MKSTEMP_O) +ac_save_LIBS="$LIBS" +LIBS="$GLIB_LIBS $LIBS" +G_ASCII_STRTOULL_C="" +G_ASCII_STRTOULL_O="" +AC_CHECK_FUNC(g_ascii_strtoull, G_ASCII_STRTOULL_O="", + [G_ASCII_STRTOULL_O="g_ascii_strtoull.o" + AC_DEFINE(NEED_G_ASCII_STRTOULL_H, 1, [Define if g_ascii_strtoull.h needs to be included]) +]) +LIBS="$ac_save_LIBS" +if test "$ac_cv_func_g_ascii_strtoull" = no ; then + G_ASCII_STRTOULL_C="g_ascii_strtoull.c" + G_ASCII_STRTOULL_O="g_ascii_strtoull.o" +fi +AC_SUBST(G_ASCII_STRTOULL_C) +AC_SUBST(G_ASCII_STRTOULL_O) + AC_CHECK_FUNC(inet_aton, INET_ATON_O="", INET_ATON_O="inet_aton.lo") if test "$ac_cv_func_inet_aton" = no ; then diff --git a/epan/Makefile.am b/epan/Makefile.am index 4a96dff9d6..933e653fd2 100644 --- a/epan/Makefile.am +++ b/epan/Makefile.am @@ -42,7 +42,9 @@ libethereal_la_SOURCES = \ $(DISSECTOR_SUPPORT_SRC) EXTRA_libethereal_la_SOURCES = \ - inet_aton.c \ + g_ascii_strtoull.c \ + g_ascii_strtoull.h \ + inet_aton.c \ inet_pton.c \ inet_ntop.c \ inet_aton.h \ @@ -67,8 +69,8 @@ MAINTAINERCLEANFILES = \ # # Add the object files for missing routines, if any. # -libethereal_la_LIBADD = @INET_ATON_O@ @INET_PTON_O@ @INET_NTOP_O@ dfilter/libdfilter.la ftypes/libftypes.la dissectors/libdissectors.la -libethereal_la_DEPENDENCIES = @INET_ATON_O@ @INET_PTON_O@ @INET_NTOP_O@ dfilter/libdfilter.la ftypes/libftypes.la dissectors/libdissectors.la +libethereal_la_LIBADD = @G_ASCII_STRTOULL_O@ @INET_ATON_O@ @INET_PTON_O@ @INET_NTOP_O@ dfilter/libdfilter.la ftypes/libftypes.la dissectors/libdissectors.la +libethereal_la_DEPENDENCIES = @G_ASCII_STRTOULL_O@ @INET_ATON_O@ @INET_PTON_O@ @INET_NTOP_O@ dfilter/libdfilter.la ftypes/libftypes.la dissectors/libdissectors.la tvbtest: tvbtest.o tvbuff.o except.o strutil.o $(LINK) -o tvbtest tvbtest.o tvbuff.o except.o strutil.o `glib-config --libs` diff --git a/epan/ftypes/ftype-integer.c b/epan/ftypes/ftype-integer.c index d55c7fbe72..e4889ff5ac 100644 --- a/epan/ftypes/ftype-integer.c +++ b/epan/ftypes/ftype-integer.c @@ -29,16 +29,20 @@ #include "ftypes-int.h" #include +#ifdef NEED_G_ASCII_STRTOULL_H +#include "g_ascii_strtoull.h" +#endif + /* * GLib 1.2[.x] doesn't define G_MAXUINT32 or G_MAXUINT64; if they're * not defined, we define them as the maximum 32-bit and 32-bit * unsigned numbers. */ #ifndef G_MAXUINT32 -#define G_MAXUINT32 ((guint32)0xFFFFFFFF) +#define G_MAXUINT32 ((guint32)0xFFFFFFFFU) #endif #ifndef G_MAXUINT64 -#define G_MAXUINT64 ((guint64)G_GINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) +#define G_MAXUINT64 ((guint64)G_GINT64_CONSTANT(0xFFFFFFFFFFFFFFFFU)) #endif static void @@ -220,7 +224,7 @@ val64_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, Log char *endptr; errno = 0; - value = strtoull(s, &endptr, 0); + value = g_ascii_strtoull(s, &endptr, 0); if (errno == EINVAL || endptr == s || *endptr != '\0') { /* This isn't a valid number. */ diff --git a/epan/g_ascii_strtoull.c b/epan/g_ascii_strtoull.c new file mode 100644 index 0000000000..45f36f34f4 --- /dev/null +++ b/epan/g_ascii_strtoull.c @@ -0,0 +1,197 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * $Id$ + * + * "g_ascii_strtoull()" extracted from GLib 2.4.5, for use with GLibs + * that don't have it (e.g., GLib 1.2[.x]). + */ + +/* + * MT safe + */ + +#include + +#include + +#include "g_ascii_strtoull.h" + +#ifndef G_MAXUINT64 +#define G_MAXUINT64 ((guint64)G_GINT64_CONSTANT(0xFFFFFFFFFFFFFFFFU)) +#endif + +/** + * g_ascii_strtoull: + * @nptr: the string to convert to a numeric value. + * @endptr: if non-%NULL, it returns the character after + * the last character used in the conversion. + * @base: to be used for the conversion, 2..36 or 0 + * + * Converts a string to a #guint64 value. + * This function behaves like the standard strtoull() function + * does in the C locale. It does this without actually + * changing the current locale, since that would not be + * thread-safe. + * + * This function is typically used when reading configuration + * files or other non-user input that should be locale independent. + * To handle input from the user you should normally use the + * locale-sensitive system strtoull() function. + * + * If the correct value would cause overflow, %G_MAXUINT64 + * is returned, and %ERANGE is stored in %errno. + * + * Return value: the #guint64 value. + * + * Since: 2.2 + **/ +guint64 +g_ascii_strtoull (const gchar *nptr, + gchar **endptr, + guint base) +{ + /* this code is based on on the strtol(3) code from GNU libc released under + * the GNU Lesser General Public License. + * + * Copyright (C) 1991,92,94,95,96,97,98,99,2000,01,02 + * Free Software Foundation, Inc. + */ +#define ISSPACE(c) ((c) == ' ' || (c) == '\f' || (c) == '\n' || \ + (c) == '\r' || (c) == '\t' || (c) == '\v') +#define ISUPPER(c) ((c) >= 'A' && (c) <= 'Z') +#define ISLOWER(c) ((c) >= 'a' && (c) <= 'z') +#define ISALPHA(c) (ISUPPER (c) || ISLOWER (c)) +#define TOUPPER(c) (ISLOWER (c) ? (c) - 'a' + 'A' : (c)) +#define TOLOWER(c) (ISUPPER (c) ? (c) - 'A' + 'a' : (c)) + gboolean negative, overflow; + guint64 cutoff; + guint64 cutlim; + guint64 ui64; + const gchar *s, *save; + guchar c; + + if (base == 1 || base > 36) + { + errno = EINVAL; + return 0; + } + + save = s = nptr; + + /* Skip white space. */ + while (ISSPACE (*s)) + ++s; + if (!*s) + goto noconv; + + /* Check for a sign. */ + negative = FALSE; + if (*s == '-') + { + negative = TRUE; + ++s; + } + else if (*s == '+') + ++s; + + /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ + if (*s == '0') + { + if ((base == 0 || base == 16) && TOUPPER (s[1]) == 'X') + { + s += 2; + base = 16; + } + else if (base == 0) + base = 8; + } + else if (base == 0) + base = 10; + + /* Save the pointer so we can check later if anything happened. */ + save = s; + cutoff = G_MAXUINT64 / base; + cutlim = G_MAXUINT64 % base; + + overflow = FALSE; + ui64 = 0; + c = *s; + for (; c; c = *++s) + { + if (c >= '0' && c <= '9') + c -= '0'; + else if (ISALPHA (c)) + c = TOUPPER (c) - 'A' + 10; + else + break; + if (c >= base) + break; + /* Check for overflow. */ + if (ui64 > cutoff || (ui64 == cutoff && c > cutlim)) + overflow = TRUE; + else + { + ui64 *= base; + ui64 += c; + } + } + + /* Check if anything actually happened. */ + if (s == save) + goto noconv; + + /* Store in ENDPTR the address of one character + past the last character we converted. */ + if (endptr) + *endptr = (gchar*) s; + + if (overflow) + { + errno = ERANGE; + return G_MAXUINT64; + } + + /* Return the result of the appropriate sign. */ + return negative ? -ui64 : ui64; + + noconv: + /* We must handle a special case here: the base is 0 or 16 and the + first two characters are '0' and 'x', but the rest are no + hexadecimal digits. This is no error case. We return 0 and + ENDPTR points to the `x`. */ + if (endptr) + { + if (save - nptr >= 2 && TOUPPER (save[-1]) == 'X' + && save[-2] == '0') + *endptr = (gchar*) &save[-1]; + else + /* There was no number to convert. */ + *endptr = (gchar*) nptr; + } + return 0; +} diff --git a/epan/g_ascii_strtoull.h b/epan/g_ascii_strtoull.h new file mode 100644 index 0000000000..dc24df0936 --- /dev/null +++ b/epan/g_ascii_strtoull.h @@ -0,0 +1,15 @@ +/* + * $Id$ + * + * "g_ascii_strtoull()" extracted from GLib 2.4.5, for use with GLibs + * that don't have it (e.g., GLib 1.2[.x]). + */ + +#ifndef __ETHEREAL_G_ASCII_STRTOULL_H__ +#define __ETHEREAL_G_ASCII_STRTOULL_H__ + +extern guint64 g_ascii_strtoull (const gchar *nptr, + gchar **endptr, + guint base); + +#endif