summaryrefslogtreecommitdiff
path: root/handy.h
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2021-04-15 10:55:32 -0600
committerKarl Williamson <khw@cpan.org>2021-08-25 11:16:34 -0600
commit296969d3c2b710adc063a323e364dae12729e066 (patch)
treedc0e351bf0a9dea3408abc3028238f36b964d2f0 /handy.h
parentf79e2ff95fbb22eaf18e130c7cba8a9d40be3d75 (diff)
downloadperl-296969d3c2b710adc063a323e364dae12729e066.tar.gz
Make paradigm into a macro
These macros use (x) | 0 to get a compiler error if x is a pointer rather than a value. This was instituted because there was confusion in them as to what they were called with. But the purpose of the paradigm wasn't obvious to even some experts; it was documented in every file in which it was used, but not at every occurrence. And, not every compiler can cope with them, it turns out. Making the paradigm into a macro, which this commit does, makes the uses self-documenting, albeit at the expense of cluttering up the macro definition somewhat; and allows the mechanism to be turned off if necessary for some compilers. Since it will be enabled for the majority of compilers, the potential bugs will be caught anyway.
Diffstat (limited to 'handy.h')
-rw-r--r--handy.h16
1 files changed, 9 insertions, 7 deletions
diff --git a/handy.h b/handy.h
index d9fdd263bc..a6266f0448 100644
--- a/handy.h
+++ b/handy.h
@@ -1424,6 +1424,10 @@ or casts
# define WIDEST_UTYPE U32
#endif
+/* Use this, where there could be some confusion, as a static assert in macros
+ * to make sure that a parameter isn't a pointer. */
+#define ASSERT_NOT_PTR(x) ((x) | 0)
+
/* FITS_IN_8_BITS(c) returns true if c doesn't have a bit set other than in
* the lower 8. It is designed to be hopefully bomb-proof, making sure that no
* bits of information are lost even on a 64-bit machine, but to get the
@@ -1459,7 +1463,8 @@ or casts
* asserts itself, once. The reason that this is necessary is that the
* duplicate asserts were exceeding the internal limits of some compilers */
#define withinCOUNT_KNOWN_VALID_(c, l, n) \
- (((WIDEST_UTYPE) (((c)) - ((l) | 0))) <= (((WIDEST_UTYPE) ((n) | 0))))
+ ((((WIDEST_UTYPE) (c)) - ASSERT_NOT_PTR(l)) \
+ <= ((WIDEST_UTYPE) ASSERT_NOT_PTR(n)))
/* Returns true if c is in the range l..u, where 'l' is non-negative
* Written this way so that after optimization, only one conditional test is
@@ -1493,17 +1498,14 @@ or casts
* unsigned type. khw supposes that it could be written as
* && ((c) == '\0' || (c) > 0)
* to avoid the message, but the cast will likely avoid extra branches even
- * with stupid compilers.
- *
- * The '| 0' part ensures a compiler error if c is not integer (like e.g.,
- * a pointer) */
-# define isASCII(c) ((WIDEST_UTYPE)((c) | 0) < 128)
+ * with stupid compilers. */
+# define isASCII(c) (((WIDEST_UTYPE) ASSERT_NOT_PTR(c)) < 128)
#endif
/* Take the eight possible bit patterns of the lower 3 bits and you get the
* lower 3 bits of the 8 octal digits, in both ASCII and EBCDIC, so those bits
* can be ignored. If the rest match '0', we have an octal */
-#define isOCTAL_A(c) (((WIDEST_UTYPE)((c) | 0) & ~7) == '0')
+#define isOCTAL_A(c) ((((WIDEST_UTYPE) ASSERT_NOT_PTR(c)) & ~7) == '0')
#ifdef H_PERL /* If have access to perl.h, lookup in its table */