perlhack: more portability musings
Jarkko Hietaniemi [Mon, 10 Jul 2006 15:41:10 +0000 (18:41 +0300)]
Message-ID: <44B24AE6.6030708@iki.fi>

p4raw-id: //depot/perl@28527

pod/perlhack.pod

index 28cea1d..5a7263c 100644 (file)
@@ -2369,7 +2369,7 @@ 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
+with that.  Related to this is the difference between "Perl_-less"
 and "Perl_-ly" APIs, for example:
 
   Perl_sv_setiv(aTHX_ ...);
@@ -2387,7 +2387,7 @@ for further discussion about context.
 Not compiling with -DDEBUGGING
 
 The DEBUGGING define exposes more code to the compiler,
-therefore more ways for things to go wrong.
+therefore more ways for things to go wrong.  You should try it.
 
 =item *
 
@@ -2424,9 +2424,14 @@ in L<perlguts>.
 
 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 as
-possible -- we will, anyway, and it's nice to save oneself from
-public embarrassment.
+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.
+
+Also study L<perlport> carefully to avoid any bad assumptions
+about the operating system, filesystem, and so forth.
+
+Do not assume an operating system indicates a certain compiler.
 
 =over 4
 
@@ -2450,10 +2455,12 @@ 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.
+macros.  Sometimes you can also play games with unions.
 
 =item *
 
@@ -2464,7 +2471,11 @@ 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".)
-Use definitions like IVSIZE, I32SIZE, and so forth.
+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 *
 
@@ -2487,13 +2498,27 @@ or maybe use temporary variables.
 
 =item *
 
+Mixing #define and #ifdef
+
+  #define BURGLE(x) ... \
+  #ifdef BURGLE_OLD_STYLE
+  ... 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 #defines, one in each #ifdef branch.
+
+=item *
+
 Using //-comments
 
   // This function bamfoodles the zorklator.
 
 That is C99 or C++.  Perl is C89.  Using the //-comments is silently
-allowed by many C compilers but cranking up the ANSI strictness (which
-we like to do) causes the compilation to fail.
+allowed by many C compilers but cranking up the ANSI C89 strictness
+(which we like to do) causes the compilation to fail.
 
 =item *
 
@@ -2505,7 +2530,16 @@ Mixing declarations and code
     set_zorkmids(n);
     int q = 4;
 
-That is C99 or C++.  Some compilers allow that, but you shouldn't.
+That is C99 or C++.  Some C compilers allow that, but you shouldn't.
+
+=item *
+
+Introducing variables inside for()
+
+  for(int i = ...; ...; ...)
+
+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 *
 
@@ -2519,9 +2553,9 @@ Mixing signed char pointers with unsigned char pointers
 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 deferencing a "naked char pointer" have an
-undefined sign: it depends on the compilers and the platform whether
-the result is signed or unsigned.
+"naked char" and therefore dereferencing a "naked char pointer" have
+an undefined signedness: it depends on the compiler and the platform
+whether the result is signed or unsigned.
 
 =item *
 
@@ -2535,10 +2569,26 @@ Pre-ANSI semantics for that was equivalent to
 
   printf("10umber = %d\10");
 
-which is probably not what you were expecting.  Unfortunately at
-least one 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.
+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 *
+
+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.
+
+=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.
 
 =back
 
@@ -2568,8 +2618,10 @@ the strlcpy/strlcat implementation of INN.
 
 Do not use sprintf() or vsprintf()
 
-Use my_snprintf() and my_vnsprintf() instead, which will try to use
-snprintf() and vsnprintf() if those safer APIs are available.
+If you really want just plain byte strings, use my_snprintf()
+and my_vnsprintf() 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