[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/5] Import idx.h from gnulib
From: |
Adhemerval Zanella |
Subject: |
[PATCH 2/5] Import idx.h from gnulib |
Date: |
Thu, 24 Dec 2020 12:16:58 -0300 |
And use to simplify stdlib/canonicalize.c implementation.
---
include/idx.h | 113 ++++++++++++++++++++++++++++++++++++++++++
stdlib/canonicalize.c | 5 +-
2 files changed, 114 insertions(+), 4 deletions(-)
create mode 100644 include/idx.h
diff --git a/include/idx.h b/include/idx.h
new file mode 100644
index 0000000000..ad7d31a2bc
--- /dev/null
+++ b/include/idx.h
@@ -0,0 +1,113 @@
+/* A type for indices and sizes.
+
+ Copyright (C) 2020 Free Software Foundation, Inc.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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 this program; if not, see <https://www.gnu.org/licenses/>. */
+
+#ifndef _IDX_H
+#define _IDX_H
+
+/* Get ptrdiff_t. */
+#include <stddef.h>
+
+/* Get PTRDIFF_MAX. */
+#include <stdint.h>
+
+/* The type 'idx_t' holds an (array) index or an (object) size.
+ Its implementation promotes to a signed integer type,
+ which can hold the values
+ 0..2^63-1 (on 64-bit platforms) or
+ 0..2^31-1 (on 32-bit platforms).
+
+ Why a signed integer type?
+
+ * Security: Signed types can be checked for overflow via
+ '-fsanitize=undefined', but unsigned types cannot.
+
+ * Comparisons without surprises: ISO C99 ?? 6.3.1.8 specifies a few
+ surprising results for comparisons, such as
+
+ (int) -3 < (unsigned long) 7 => false
+ (int) -3 < (unsigned int) 7 => false
+ and on 32-bit machines:
+ (long) -3 < (unsigned int) 7 => false
+
+ This is surprising because the natural comparison order is by
+ value in the realm of infinite-precision signed integers (???).
+
+ The best way to get rid of such surprises is to use signed types
+ for numerical integer values, and use unsigned types only for
+ bit masks and enums.
+
+ Why not use 'size_t' directly?
+
+ * Because 'size_t' is an unsigned type, and a signed type is better.
+ See above.
+
+ Why not use 'ptrdiff_t' directly?
+
+ * Maintainability: When reading and modifying code, it helps to know that
+ a certain variable cannot have negative values. For example, when you
+ have a loop
+
+ int n = ...;
+ for (int i = 0; i < n; i++) ...
+
+ or
+
+ ptrdiff_t n = ...;
+ for (ptrdiff_t i = 0; i < n; i++) ...
+
+ you have to ask yourself "what if n < 0?". Whereas in
+
+ idx_t n = ...;
+ for (idx_t i = 0; i < n; i++) ...
+
+ you know that this case cannot happen.
+
+ Similarly, when a programmer writes
+
+ idx_t = ptr2 - ptr1;
+
+ there is an implied assertion that ptr1 and ptr2 point into the same
+ object and that ptr1 <= ptr2.
+
+ * Being future-proof: In the future, range types (integers which are
+ constrained to a certain range of values) may be added to C compilers
+ or to the C standard. Several programming languages (Ada, Haskell,
+ Common Lisp, Pascal) already have range types. Such range types may
+ help producing good code and good warnings. The type 'idx_t' could
+ then be typedef'ed to a range type that is signed after promotion. */
+
+/* In the future, idx_t could be typedef'ed to a signed range type.
+ The clang "extended integer types", supported in Clang 11 or newer
+
<https://clang.llvm.org/docs/LanguageExtensions.html#extended-integer-types>,
+ are a special case of range types. However, these types don't support
binary
+ operators with plain integer types (e.g. expressions such as x > 1).
+ Therefore, they don't behave like signed types (and not like unsigned types
+ either). So, we cannot use them here. */
+
+/* Use the signed type 'ptrdiff_t'. */
+/* Note: ISO C does not mandate that 'size_t' and 'ptrdiff_t' have the same
+ size, but it is so on all platforms we have seen since 1990. */
+typedef ptrdiff_t idx_t;
+
+/* IDX_MAX is the maximum value of an idx_t. */
+#define IDX_MAX PTRDIFF_MAX
+
+/* So far no need has been found for an IDX_WIDTH macro.
+ Perhaps there should be another macro IDX_VALUE_BITS that does not
+ count the sign bit and is therefore one less than PTRDIFF_WIDTH. */
+
+#endif /* _IDX_H */
diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c
index 66685f4526..4b3bd10a9d 100644
--- a/stdlib/canonicalize.c
+++ b/stdlib/canonicalize.c
@@ -35,14 +35,13 @@
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <idx.h>
#include <scratch_buffer.h>
#ifdef _LIBC
# include <eloop-threshold.h>
# include <shlib-compat.h>
-typedef ptrdiff_t idx_t;
-# define IDX_MAX PTRDIFF_MAX
# define FILE_SYSTEM_PREFIX_LEN(name) 0
# define IS_ABSOLUTE_FILE_NAME(name) ISSLASH(*(name))
# define ISSLASH(c) ((c) == '/')
@@ -50,7 +49,6 @@ typedef ptrdiff_t idx_t;
#else
# define __canonicalize_file_name canonicalize_file_name
# define __realpath realpath
-# include "idx.h"
# include "pathmax.h"
# include "filename.h"
# if defined _WIN32 && !defined __CYGWIN__
@@ -92,7 +90,6 @@ typedef ptrdiff_t idx_t;
#endif
#if !FUNC_REALPATH_WORKS || defined _LIBC
-
static idx_t
get_path_max (void)
{
--
2.25.1