How do a write portable programs?

Doug Gwyn gwyn at smoke.ARPA
Thu Sep 8 14:59:35 AEST 1988


In article <1056 at nmtsun.nmt.edu> warner at hydrovax.nmt.edu (M. Warner Losh) writes:
>How do I write program that are easily protable when I HAVE TO use the
>system calls (be they setitimer() or lib$init_timer() or int21()...).  Is
>there a good and easy way that I can write my programs so that most of the
>code never has to be touched when I port?  What is the best way of handling
>system dependent routines?  Assume the whole world is UNIX and then write
>UNIX system call emulation on those that aren't?  Or should I write
>routines that will do some functions (say turn off echo, but that is a bad
>example) regardless of how that function gets done.  Should I use zillions
>of #ifdefs everywhere? or should there be files that contain source code
>for only one system? 

There is one basic answer to all these questions:  Encapsulate system
dependencies in a set of interface modules, where you have carefully
designed the interface to be as general as possible while providing
the necessary functionality to support your application(s).  For
example, even though some systems support record locking, others
don't, so if you need data integrity while updating records in a file
see if you can arrange things so that whole-file locking will work
acceptably.  Then implement a simple lock/unlock file interface that
does whatever is necessary to lock an entire file.  In a single-user
environment, these will be no-ops, in an old UNIX environment, you
can probably use the "link to the file" kludge, and a 4BSD or SVR2.2
or later environment provides direct kernel support for file locking.

The important point is that your applications proper contain
"universal" calls to the appropriate interface routines; when porting,
only the internals of the interface routines (which should be kept in
separate source files) should require revision.  This is just an
extension of the "C library" approach, and it works quite well
provided that the system interface is well designed.

It doesn't take many #ifdefs to make one's code virtually unreadable,
and one has the problem of properly parameterizing them, which is not
as easy as one might think due to the existence of a variety of
"hybrid" environments.  (For example, a "SYSV" parameter might
not discriminate sufficiently on a mostly-4BSD system with some SYSV
features added, or vice-versa).

By the way, associated with the "universal" system interfaces are
normally one or more headers that declare the functions, define
constants, etc.  You can use such a header to accommodate the lack of
a "void" type, and so forth, but don't overdo it or nobody except
possibly you will be able to read your application's source code.



More information about the Comp.lang.c mailing list