+=head3 Other environment variables that may influence tests
+
+=over 4
+
+=item PERL_TEST_Net_Ping
+
+Setting this variable runs all the Net::Ping modules tests,
+otherwise some tests that interact with the outside world are skipped.
+See L<perl58delta>.
+
+=item PERL_TEST_NOVREXX
+
+Setting this variable skips the vrexx.t tests for OS2::REXX.
+
+=item PERL_TEST_NUMCONVERTS
+
+This sets a variable in op/numconvert.t.
+
+=back
+
+See also the documentation for the Test and Test::Harness modules,
+for more environment variables that affect testing.
+
+=head2 Common problems when patching Perl source code
+
+Perl source plays by ANSI C89 rules: no C99 (or C++) extensions. In
+some cases we have to take pre-ANSI requirements into consideration.
+You don't care about some particular platform having broken Perl?
+I hear there is still a strong demand for J2EE programmers.
+
+=head2 Perl environment problems
+
+=over 4
+
+=item *
+
+Not compiling with threading
+
+Compiling with threading (-Duseithreads) completely rewrites
+the function prototypes of Perl. You better try your changes
+with that. Related to this is the difference between "Perl_-less"
+and "Perl_-ly" APIs, for example:
+
+ Perl_sv_setiv(aTHX_ ...);
+ sv_setiv(...);
+
+The first one explicitly passes in the context, which is needed for e.g.
+threaded builds. The second one does that implicitly; do not get them
+mixed. If you are not passing in a aTHX_, you will need to do a dTHX
+(or a dVAR) as the first thing in the function.
+
+See L<perlguts/"How multiple interpreters and concurrency are supported">
+for further discussion about context.
+
+=item *
+
+Not compiling with -DDEBUGGING
+
+The DEBUGGING define exposes more code to the compiler,
+therefore more ways for things to go wrong. You should try it.
+
+=item *
+
+Introducing (non-read-only) globals
+
+Do not introduce any modifiable globals, truly global or file static.
+They are bad form and complicate multithreading and other forms of
+concurrency. The right way is to introduce them as new interpreter
+variables, see F<intrpvar.h> (at the very end for binary compatibility).
+
+Introducing read-only (const) globals is okay, as long as you verify
+with e.g. C<nm libperl.a|egrep -v ' [TURtr] '> (if your C<nm> has
+BSD-style output) that the data you added really is read-only.
+(If it is, it shouldn't show up in the output of that command.)
+
+If you want to have static strings, make them constant:
+
+ static const char etc[] = "...";
+
+If you want to have arrays of constant strings, note carefully
+the right combination of C<const>s:
+
+ static const char * const yippee[] =
+ {"hi", "ho", "silver"};
+
+There is a way to completely hide any modifiable globals (they are all
+moved to heap), the compilation setting C<-DPERL_GLOBAL_STRUCT_PRIVATE>.
+It is not normally used, but can be used for testing, read more
+about it in L<perlguts/"Background and PERL_IMPLICIT_CONTEXT">.
+
+=item *
+
+Not exporting your new function
+
+Some platforms (Win32, AIX, VMS, OS/2, to name a few) require any
+function that is part of the public API (the shared Perl library)
+to be explicitly marked as exported. See the discussion about
+F<embed.pl> in L<perlguts>.
+
+=item *
+
+Exporting your new function
+
+The new shiny result of either genuine new functionality or your
+arduous refactoring is now ready and correctly exported. So what
+could possibly go wrong?
+
+Maybe simply that your function did not need to be exported in the
+first place. Perl has a long and not so glorious history of exporting
+functions that it should not have.
+
+If the function is used only inside one source code file, make it
+static. See the discussion about F<embed.pl> in L<perlguts>.
+
+If the function is used across several files, but intended only for
+Perl's internal use (and this should be the common case), do not
+export it to the public API. See the discussion about F<embed.pl>
+in L<perlguts>.
+
+=back
+
+=head2 Portability problems
+
+The following are common causes of compilation and/or execution
+failures, not common to Perl as such. The C FAQ is good bedtime
+reading. Please test your changes with as many C compilers and
+platforms as possible -- we will, anyway, and it's nice to save
+oneself from public embarrassment.
+
+If using gcc, you can add the C<-std=c89> option which will hopefully
+catch most of these unportabilities. (However it might also catch
+incompatibilities in your system's header files.)
+
+Use the Configure C<-Dgccansipedantic> flag to enable the gcc
+C<-ansi -pedantic> flags which enforce stricter ANSI rules.
+
+If using the C<gcc -Wall> note that not all the possible warnings
+(like C<-Wunitialized>) are given unless you also compile with C<-O>.
+
+Note that if using gcc, starting from Perl 5.9.5 the Perl core source
+code files (the ones at the top level of the source code distribution,
+but not e.g. the extensions under ext/) are automatically compiled
+with as many as possible of the C<-std=c89>, C<-ansi>, C<-pedantic>,
+and a selection of C<-W> flags (see cflags.SH).
+
+Also study L<perlport> carefully to avoid any bad assumptions
+about the operating system, filesystems, and so forth.
+
+You may once in a while try a "make microperl" to see whether we
+can still compile Perl with just the bare minimum of interfaces.
+(See README.micro.)
+
+Do not assume an operating system indicates a certain compiler.
+
+=over 4
+
+=item *
+
+Casting pointers to integers or casting integers to pointers
+
+ void castaway(U8* p)
+ {
+ IV i = p;
+
+or
+
+ void castaway(U8* p)
+ {
+ IV i = (IV)p;
+
+Both are bad, and broken, and unportable. Use the PTR2IV()
+macro that does it right. (Likewise, there are PTR2UV(), PTR2NV(),
+INT2PTR(), and NUM2PTR().)
+
+=item *
+
+Casting between data function pointers and data pointers
+
+Technically speaking casting between function pointers and data
+pointers is unportable and undefined, but practically speaking
+it seems to work, but you should use the FPTR2DPTR() and DPTR2FPTR()
+macros. Sometimes you can also play games with unions.
+
+=item *
+
+Assuming sizeof(int) == sizeof(long)
+
+There are platforms where longs are 64 bits, and platforms where ints
+are 64 bits, and while we are out to shock you, even platforms where
+shorts are 64 bits. This is all legal according to the C standard.
+(In other words, "long long" is not a portable way to specify 64 bits,
+and "long long" is not even guaranteed to be any wider than "long".)
+
+Instead, use the definitions IV, UV, IVSIZE, I32SIZE, and so forth.
+Avoid things like I32 because they are B<not> guaranteed to be
+I<exactly> 32 bits, they are I<at least> 32 bits, nor are they
+guaranteed to be B<int> or B<long>. If you really explicitly need
+64-bit variables, use I64 and U64, but only if guarded by HAS_QUAD.
+
+=item *
+
+Assuming one can dereference any type of pointer for any type of data
+
+ char *p = ...;
+ long pony = *p; /* BAD */
+
+Many platforms, quite rightly so, will give you a core dump instead
+of a pony if the p happens not be correctly aligned.
+
+=item *
+
+Lvalue casts
+
+ (int)*p = ...; /* BAD */
+
+Simply not portable. Get your lvalue to be of the right type,
+or maybe use temporary variables, or dirty tricks with unions.
+
+=item *
+
+Assume B<anything> about structs (especially the ones you
+don't control, like the ones coming from the system headers)
+
+=over 8
+
+=item *
+
+That a certain field exists in a struct
+
+=item *
+
+That no other fields exist besides the ones you know of
+
+=item *
+
+That a field is of certain signedness, sizeof, or type
+
+=item *
+
+That the fields are in a certain order
+
+=over 8
+
+=item *
+
+While C guarantees the ordering specified in the struct definition,
+between different platforms the definitions might differ
+
+=back
+
+=item *
+
+That the sizeof(struct) or the alignments are the same everywhere
+
+=over 8
+
+=item *
+
+There might be padding bytes between the fields to align the fields -
+the bytes can be anything
+
+=item *
+
+Structs are required to be aligned to the maximum alignment required
+by the fields - which for native types is for usually equivalent to
+sizeof() of the field
+
+=back
+
+=back
+
+=item *
+
+Assuming the character set is ASCIIish
+
+Perl can compile and run under EBCDIC platforms. See L<perlebcdic>.
+This is transparent for the most part, but because the character sets
+differ, you shouldn't use numeric (decimal, octal, nor hex) constants
+to refer to characters. You can safely say 'A', but not 0x41.
+You can safely say '\n', but not \012.
+If a character doesn't have a trivial input form, you can
+create a #define for it in both C<utfebcdic.h> and C<utf8.h>, so that
+it resolves to different values depending on the character set being used.
+(There are three different EBCDIC character sets defined in C<utfebcdic.h>,
+so it might be best to insert the #define three times in that file.)
+
+Also, the range 'A' - 'Z' in ASCII is an unbroken sequence of 26 upper case
+alphabetic characters. That is not true in EBCDIC. Nor for 'a' to 'z'.
+But '0' - '9' is an unbroken range in both systems. Don't assume anything
+about other ranges.
+
+Many of the comments in the existing code ignore the possibility of EBCDIC,
+and may be wrong therefore, even if the code works.
+This is actually a tribute to the successful transparent insertion of being
+able to handle EBCDIC without having to change pre-existing code.
+
+UTF-8 and UTF-EBCDIC are two different encodings used to represent Unicode
+code points as sequences of bytes. Macros
+with the same names (but different definitions)
+in C<utf8.h> and C<utfebcdic.h>
+are used to allow the calling code to think that there is only one such
+encoding.
+This is almost always referred to as C<utf8>, but it means the EBCDIC version
+as well. Again, comments in the code may well be wrong even if the code itself
+is right.
+For example, the concept of C<invariant characters> differs between ASCII and
+EBCDIC.
+On ASCII platforms, only characters that do not have the high-order
+bit set (i.e. whose ordinals are strict ASCII, 0 - 127)
+are invariant, and the documentation and comments in the code
+may assume that,
+often referring to something like, say, C<hibit>.
+The situation differs and is not so simple on EBCDIC machines, but as long as
+the code itself uses the C<NATIVE_IS_INVARIANT()> macro appropriately, it
+works, even if the comments are wrong.
+
+=item *
+
+Assuming the character set is just ASCII
+
+ASCII is a 7 bit encoding, but bytes have 8 bits in them. The 128 extra
+characters have different meanings depending on the locale. Absent a locale,
+currently these extra characters are generally considered to be unassigned,
+and this has presented some problems.
+This is scheduled to be changed in 5.12 so that these characters will
+be considered to be Latin-1 (ISO-8859-1).
+
+=item *
+
+Mixing #define and #ifdef
+
+ #define BURGLE(x) ... \
+ #ifdef BURGLE_OLD_STYLE /* BAD */
+ ... do it the old way ... \
+ #else
+ ... do it the new way ... \
+ #endif
+
+You cannot portably "stack" cpp directives. For example in the above
+you need two separate BURGLE() #defines, one for each #ifdef branch.
+
+=item *
+
+Adding non-comment stuff after #endif or #else
+
+ #ifdef SNOSH
+ ...
+ #else !SNOSH /* BAD */
+ ...
+ #endif SNOSH /* BAD */
+
+The #endif and #else cannot portably have anything non-comment after
+them. If you want to document what is going (which is a good idea
+especially if the branches are long), use (C) comments:
+
+ #ifdef SNOSH
+ ...
+ #else /* !SNOSH */
+ ...
+ #endif /* SNOSH */
+
+The gcc option C<-Wendif-labels> warns about the bad variant
+(by default on starting from Perl 5.9.4).
+
+=item *
+
+Having a comma after the last element of an enum list
+
+ enum color {
+ CERULEAN,
+ CHARTREUSE,
+ CINNABAR, /* BAD */
+ };
+
+is not portable. Leave out the last comma.
+
+Also note that whether enums are implicitly morphable to ints
+varies between compilers, you might need to (int).
+
+=item *
+
+Using //-comments
+
+ // This function bamfoodles the zorklator. /* BAD */
+
+That is C99 or C++. Perl is C89. Using the //-comments is silently
+allowed by many C compilers but cranking up the ANSI C89 strictness
+(which we like to do) causes the compilation to fail.
+
+=item *
+
+Mixing declarations and code
+
+ void zorklator()
+ {
+ int n = 3;
+ set_zorkmids(n); /* BAD */
+ int q = 4;
+
+That is C99 or C++. Some C compilers allow that, but you shouldn't.
+
+The gcc option C<-Wdeclaration-after-statements> scans for such problems
+(by default on starting from Perl 5.9.4).
+
+=item *
+
+Introducing variables inside for()
+
+ for(int i = ...; ...; ...) { /* BAD */
+
+That is C99 or C++. While it would indeed be awfully nice to have that
+also in C89, to limit the scope of the loop variable, alas, we cannot.
+
+=item *
+
+Mixing signed char pointers with unsigned char pointers
+
+ int foo(char *s) { ... }
+ ...
+ unsigned char *t = ...; /* Or U8* t = ... */
+ foo(t); /* BAD */
+
+While this is legal practice, it is certainly dubious, and downright
+fatal in at least one platform: for example VMS cc considers this a
+fatal error. One cause for people often making this mistake is that a
+"naked char" and therefore dereferencing a "naked char pointer" have
+an undefined signedness: it depends on the compiler and the flags of
+the compiler and the underlying platform whether the result is signed
+or unsigned. For this very same reason using a 'char' as an array
+index is bad.
+
+=item *
+
+Macros that have string constants and their arguments as substrings of
+the string constants
+
+ #define FOO(n) printf("number = %d\n", n) /* BAD */
+ FOO(10);
+
+Pre-ANSI semantics for that was equivalent to
+
+ printf("10umber = %d\10");
+
+which is probably not what you were expecting. Unfortunately at least
+one reasonably common and modern C compiler does "real backward
+compatibility" here, in AIX that is what still happens even though the
+rest of the AIX compiler is very happily C89.
+
+=item *
+
+Using printf formats for non-basic C types
+
+ IV i = ...;
+ printf("i = %d\n", i); /* BAD */
+
+While this might by accident work in some platform (where IV happens
+to be an C<int>), in general it cannot. IV might be something larger.
+Even worse the situation is with more specific types (defined by Perl's
+configuration step in F<config.h>):
+
+ Uid_t who = ...;
+ printf("who = %d\n", who); /* BAD */
+
+The problem here is that Uid_t might be not only not C<int>-wide
+but it might also be unsigned, in which case large uids would be
+printed as negative values.
+
+There is no simple solution to this because of printf()'s limited
+intelligence, but for many types the right format is available as
+with either 'f' or '_f' suffix, for example:
+
+ IVdf /* IV in decimal */
+ UVxf /* UV is hexadecimal */
+
+ printf("i = %"IVdf"\n", i); /* The IVdf is a string constant. */
+
+ Uid_t_f /* Uid_t in decimal */
+
+ printf("who = %"Uid_t_f"\n", who);
+
+Or you can try casting to a "wide enough" type:
+
+ printf("i = %"IVdf"\n", (IV)something_very_small_and_signed);
+
+Also remember that the C<%p> format really does require a void pointer:
+
+ U8* p = ...;
+ printf("p = %p\n", (void*)p);
+
+The gcc option C<-Wformat> scans for such problems.
+
+=item *
+
+Blindly using variadic macros
+
+gcc has had them for a while with its own syntax, and C99 brought
+them with a standardized syntax. Don't use the former, and use
+the latter only if the HAS_C99_VARIADIC_MACROS is defined.
+
+=item *
+
+Blindly passing va_list
+
+Not all platforms support passing va_list to further varargs (stdarg)
+functions. The right thing to do is to copy the va_list using the
+Perl_va_copy() if the NEED_VA_COPY is defined.
+
+=item *
+
+Using gcc statement expressions
+
+ val = ({...;...;...}); /* BAD */
+
+While a nice extension, it's not portable. The Perl code does
+admittedly use them if available to gain some extra speed
+(essentially as a funky form of inlining), but you shouldn't.
+
+=item *
+
+Binding together several statements in a macro
+
+Use the macros STMT_START and STMT_END.
+
+ STMT_START {
+ ...
+ } STMT_END
+
+=item *
+
+Testing for operating systems or versions when should be testing for features
+
+ #ifdef __FOONIX__ /* BAD */
+ foo = quux();
+ #endif
+
+Unless you know with 100% certainty that quux() is only ever available
+for the "Foonix" operating system B<and> that is available B<and>
+correctly working for B<all> past, present, B<and> future versions of
+"Foonix", the above is very wrong. This is more correct (though still
+not perfect, because the below is a compile-time check):
+
+ #ifdef HAS_QUUX
+ foo = quux();
+ #endif
+
+How does the HAS_QUUX become defined where it needs to be? Well, if
+Foonix happens to be UNIXy enough to be able to run the Configure
+script, and Configure has been taught about detecting and testing
+quux(), the HAS_QUUX will be correctly defined. In other platforms,
+the corresponding configuration step will hopefully do the same.
+
+In a pinch, if you cannot wait for Configure to be educated,
+or if you have a good hunch of where quux() might be available,
+you can temporarily try the following:
+
+ #if (defined(__FOONIX__) || defined(__BARNIX__))
+ # define HAS_QUUX
+ #endif
+
+ ...
+
+ #ifdef HAS_QUUX
+ foo = quux();
+ #endif
+
+But in any case, try to keep the features and operating systems separate.
+
+=back
+
+=head2 Problematic System Interfaces
+
+=over 4
+
+=item *
+
+malloc(0), realloc(0), calloc(0, 0) are non-portable. To be portable
+allocate at least one byte. (In general you should rarely need to
+work at this low level, but instead use the various malloc wrappers.)
+
+=item *
+
+snprintf() - the return type is unportable. Use my_snprintf() instead.
+
+=back
+
+=head2 Security problems
+
+Last but not least, here are various tips for safer coding.
+
+=over 4
+
+=item *
+
+Do not use gets()
+
+Or we will publicly ridicule you. Seriously.
+
+=item *
+
+Do not use strcpy() or strcat() or strncpy() or strncat()
+
+Use my_strlcpy() and my_strlcat() instead: they either use the native
+implementation, or Perl's own implementation (borrowed from the public
+domain implementation of INN).
+
+=item *
+
+Do not use sprintf() or vsprintf()
+
+If you really want just plain byte strings, use my_snprintf()
+and my_vsnprintf() instead, which will try to use snprintf() and
+vsnprintf() if those safer APIs are available. If you want something
+fancier than a plain byte string, use SVs and Perl_sv_catpvf().
+
+=back
+