|
9.1.5 Fallback Function Implementations
Due to the huge number of Unix varieties in common use today, many of
the C library functions that you take for granted on your preferred
development platform are very likely missing from some of the
architectures you would like your code to compile on. Fundamentally
there are two ways to cope with this:
-
Use only the few library calls that are available everywhere. In
reality this is not actually possible because there are two lowest
common denominators with mutually exclusive APIs, one rooted in
BSD Unix (`bcopy', `rindex') and the other in
SYSV Unix (`memcpy', `strrchr'). The only way to deal
with this is to define one API in terms of the other using the
preprocessor. The newer POSIX standard deprecates many of the
BSD originated calls (with exceptions such as the
BSD socket API). Even on non-POSIX platforms, there
has been so much cross pollination that often both varieties of a given
call may be provided, however you would be wise to write your code
using POSIX endorsed calls, and where they are missing, define them
in terms of whatever the host platform provides.
This approach requires a lot of knowledge about various system libraries
and standards documents, and can leave you with reams of preprocessor
code to handle the differences between APIS. You will also need
to perform a lot of checking in `configure.in' to figure out which
calls are available. For example, to allow the rest of your code to use
the `strcpy' call with impunity, you would need the following code
in `configure.in':
|
AC_CHECK_FUNCS(strcpy bcopy)
|
And the following preprocessor code in a header file that is seen by
every source file:
|
#if !HAVE_STRCPY
# if HAVE_BCOPY
# define strcpy(dest, src) bcopy (src, dest, 1 + strlen (src))
# else /* !HAVE_BCOPY */
error no strcpy or bcopy
# endif /* HAVE_BCOPY */
#endif /* HAVE_STRCPY */
|
-
Alternatively you could provide your own fallback implementations of
function calls you know are missing on some platforms. In practice you
don't need to be as knowledgeable about problematic functions when using
this approach. You can look in GNU libiberty(9) or François
Pinard's libit project(10) to see for which
functions other GNU developers have needed to implement fallback
code. The libit project is especially useful in this respect as it
comprises canonical versions of fallback functions, and suitable
Autoconf macros assembled from across the entire GNU project. I
won't give an example of setting up your package to use this approach,
since that is how I have chosen to structure the project described in
this chapter.
Rather than writing code to the lowest common denominator of system
libraries, I am a strong advocate of the latter school of thought in the
majority of cases. As with all things it pays to take a pragmatic
approach; don't be afraid of the middle ground -- weigh the options on
a case by case basis.
|