figure out anyway. Also try to allow for Configure command-line
overrides.
+=head1 Working around compiler bugs
+
+Occasionally, the root cause of a bug in perl turns out to be due to a bug
+in the compiler. Often, changing the compilation options (particularly the
+optimization level) can work around the bug. However, if you try to do
+this on the command line, you will be changing the compilation options for
+every component of perl, which can really hurt perl's performance.
+Instead, consider placing a test case into the hints directory to detect
+whether the compiler bug is present, and add logic to the hints file to
+take a specific and appropriate action
+
+=head2 Test-case conventions
+
+Test cases should be named "tNNN.c", where NNN is the next unused sequence
+number. The test case must be executable and should display a message
+containing the word "fails" when the compiler bug is present. It should
+display the word "works" with the compiler bug is not present. The test
+cases should be liberally commented and may be used by any hints file that
+needs them. See the first hints file (t001.c) for an example.
+
+=head2 Hint file processing
+
+The hint file must define a call-back unit (see below) that will compile,
+link, and run the test case, and then check for the presence of the string
+"fails" in the output. If it finds this string, it sets a special variable
+to specify the compilation option(s) for the specific perl source file that
+is affected by the bug.
+
+The special variable is named "XXX_cflags" where "XXX" is the name of
+the source file (without the ".c" suffix). The value of this variable
+is the string "optimize=YYY", where "YYY" is the compilation option
+necessary to work around the bug. The default value of this variable
+is "-O" (letter O), which specifies that the C compiler should compile
+the source program at the default optimization level. If you can
+avoid the compiler bug by disabling optimization, just reset the
+"optimize" variable to the null string. Sometimes a bug is present at
+a higher optimization level (say, O3) and not present at a lower
+optimization level (say, O1). In this case, you should specify the
+highest optimization level at which the bug is not present, so that
+you will retain as many of the benefits of code optimization as
+possible.
+
+For example, if the pp_pack.c source file must be compiled at
+optimization level 0 to work around a problem on a particular
+platform, one of the statements
+
+ pp_pack_cflags="optimize=-O0" or
+ pp_pack_cflags="optimize="
+
+will do the trick, since level 0 is equivalent to no optimization.
+(In case your printer or display device does not distinguish the
+letter O from the digit 0, that is the letter O followed by the digit
+0). You can specify any compiler option or set of options here, not
+just optimizer options. These options are appended to the list of all
+other compiler options, so you should be able to override almost any
+compiler option prepared by Configure. (Obviously this depends on how
+the compiler treats conflicting options, but most seem to go with the
+last value specified on the command line).
+
+You should also allow for the XXX_cflags variable to be overridden on the
+command line.
+
+See the vos.sh hints file for an extended example of these techniques.
+
=head1 Hint file tricks
=head2 Printing critical messages
=over 4
-=item Warning
-
-All of the following is experimental and subject to change. But it
-probably won't change much. :-)
-
=item Compiler-related flags
The settings of some things, such as optimization flags, may depend on
-the particular compiler used. For example, for ISC we have the
-following:
+the particular compiler used. For example, consider the following:
case "$cc" in
*gcc*) ccflags="$ccflags -posix"
Have the appropriate amount of fun :-)
- Andy Dougherty doughera@lafayette.edu
+ Andy Dougherty doughera@lafayette.edu (author)
+ Paul Green paul.green@stratus.com (compiler bugs)
--- /dev/null
+/* Beginning of modification history */
+/* Written 02-04-10 by Paul Green (Paul.Green@stratus.com) */
+/* End of modification history */
+
+/* This test case is extracted from Perl version 5.7.3. It is
+ in the Perl_unpack_str function of the pp_pack.c source file.
+
+ GCC 2.95.2 improperly assumes that it can compensate for an
+ extra fsub by performing a fadd. This would work in
+ fixed-point arithmetic, but does not work in floating-point
+ arithmetic.
+
+ This problem has been seen on HP-UX and on Stratus VOS, both
+ of which have an HP PA-RISC target (hppa1.1). The Stratus
+ bug number is gnu_g++-220. */
+
+/* #define _POSIX_C_SOURCE 199506L -- added by Configure */
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+void test(double *result)
+{
+ float afloat;
+ double adouble;
+ int checksum = 0;
+ unsigned cuv = 0;
+ double cdouble = 0.0;
+ const int bits_in_uv = 8 * sizeof(cuv);
+
+ checksum = 53;
+ cdouble = -1.0;
+
+ if (checksum) {
+ if (checksum > bits_in_uv) {
+ double trouble;
+
+ adouble = (double) (1 << (checksum & 15));
+
+ while (checksum >= 16) {
+ checksum -= 16;
+ adouble *= 65536.0;
+ }
+
+ /* At -O1, GCC 2.95.2 compiles the following loop
+ into:
+
+ L$0014
+ fcmp,dbl,>= %fr4,%fr0
+ ftest
+ b L$0014
+ fadd,dbl %fr4,%fr12,%fr4
+ fsub,dbl %fr4,%fr12,%fr4
+
+ This code depends on the floading-add and
+ floating-subtract retaining all of the
+ precision present in the operands. There is
+ no such guarantee when using floating-point,
+ as this test case demonstrates.
+
+ The code is okay at -O0. */
+
+ while (cdouble < 0.0)
+ cdouble += adouble;
+
+ cdouble = modf (cdouble / adouble, &trouble) * adouble;
+ }
+ }
+
+ *result = cdouble;
+}
+
+int main (int argc, char ** argv)
+{
+double value;
+
+ test (&value);
+
+ if (argc == 2 && !strcmp(argv[1],"-v"))
+ printf ("value = %.18e\n", value);
+
+ if (value != 9.007199254740991e+15) {
+ printf ("t001 fails!\n");
+ return -1;
+ }
+ else {
+ printf ("t001 works.\n");
+ return 0;
+ }
+}
# VOS does not have socketpair() but we supply one in vos.c
d_sockpair="define"
+
+# Once we have the compiler flags defined, Configure will
+# execute the following call-back script. See hints/README.hints
+# for details.
+cat > UU/cc.cbu <<'EOCBU'
+# This script UU/cc.cbu will get 'called-back' by Configure after it
+# has prompted the user for the C compiler to use.
+
+# Compile and run the a test case to see if bug gnu_g++-220 is
+# present. If so, lower the optimization level when compiling
+# pp_pack.c. This works around a bug in unpack.
+
+echo " "
+echo "Testing whether bug gnu_g++-220 is fixed in your compiler..."
+
+# Try compiling the test case.
+if $cc -o t001 -O $ccflags $ldflags ../hints/t001.c; then
+ gccbug=`$run ./t001`
+ case "$gccbug" in
+ *fails*) gccversion=`$cc --version`
+ cat >&4 <<EOF
+This C compiler ($gccversion) is known to have optimizer
+problems when compiling pp_pack.c. The Stratus bug number
+for this problem is gnu_g++-220.
+
+Disabling optimization for pp_pack.c.
+EOF
+ case "$pp_pack_cflags" in
+ '') pp_pack_cflags='optimize='
+ echo "pp_pack_cflags='optimize=\"\"'" >> config.sh ;;
+ *) echo "You specified pp_pack_cflags yourself, so we'll go with your value." >&4 ;;
+ esac
+ ;;
+ *) echo "Your compiler is ok." >&4
+ ;;
+ esac
+else
+ echo " "
+ echo "*** WHOA THERE!!! ***" >&4
+ echo " Your C compiler \"$cc\" doesn't seem to be working!" >&4
+ case "$knowitall" in
+ '')
+ echo " You'd better start hunting for one and let me know about it." >&4
+ exit 1
+ ;;
+ esac
+fi
+
+$rm -f t001$_o t001$_exe t001.kp
+EOCBU