[comp.lang.c] Portability Issues

ming@plxsun.uucp (Lak-Ming Lam) (04/24/91)

I would like to develop program which can be portable to different system
(e.g. PC/MS-DOS, UNIX, Mac OS, etc.).  I would like to have anyone of you
help me on the following issues:

o	what need to be aware of (e.g. word size, byte order, etc.)
o	how to use one set of source code to support different systems
	(using #if MSDOS etc. or some other ways)
o	information that are already available on this issus
	(e.g. Usenet postings, technical papers, books, etc.)
o	example source code for applications which can run on different
	systems

sjs@gnv.ifas.ufl.edu (04/24/91)

In article <2573@plx.UUCP>, ming@plxsun.uucp (Lak-Ming Lam) writes:
> I would like to develop program which can be portable to different system
> (e.g. PC/MS-DOS, UNIX, Mac OS, etc.).  I would like to have anyone of you
> help me on the following issues:
> 
> ...
> o	how to use one set of source code to support different systems
> 	(using #if MSDOS etc. or some other ways)
> ...

I write in C for the PC and a VAX.  I have a special include files whose
contents are different on the PC and VAX, so I don't have to change the
specifications in the source code.  Example:

#include "setups.h"

where the contents on the PC would be for PC-specific setups, and the
contents on the VAX would be for VAX-specific setups.

At places where I have to use a machine-specific function (like keyboard
handlers), I make a common name that I use throughout my code, and supply
the machine-specific reference on the appropriate computer.  For example:

	get_key_press (&key_value);

The setups.h file on the PC may use a #define or a full function to
take care of the keypress routine on the PC; the setups.h file on the
VAX would define or use VAX-specific functions.  I'd use #defines to
assign words like EXIT or CANCEL to represent the key functions instead
of passing back actual key values; this will make it easier to set
things up in a switch block.

The object is to create a maximum core of code that will work unchanged
on more than one computer; supply computer-specific code in separate
.h or .c files, which each residing on its respective machine.

While this may result in some nested function calls to finally
get to a computer-specific function, it will be much easier to
manage.  Unless speed is very critical, given the number of machines
you are going to write your code for, I'd trade a few clock ticks
for maximum common code.


 +---------------------------------------------+------------------------------+
 |     ~~~     Borco                           | "Time to wake up!            |
 |   / \ ~~~   at the Mountains of Madness     |    Time to rise!"            |
 |  /  / \                                     |                              |
 | /  /   \    Bitnet:    sjs@ifasgnv          | - Silver Lady,               |
 |   /     \   Internet:  sjs@gnv.ifas.ufl.edu |   Intergalactic Touring Band |
 +---------------------------------------------+------------------------------+

jeffb@aquifer.geology.uiuc.edu (Jeffrey Biesiadecki) (04/25/91)

Hi -

Last November the eighth version of a paper with some tips for writing
portable programs in C was made available.  I don't know if it is the most
current version of the paper.

Here's an exceprt from a note posted (here, I think).  It gives the
names of the paper and the authors, and where to get the paper.  I
hope they don't mind the free plug...

Jeff

>From: gvr@cs.brown.edu (George V. Reilly)
>Date: 30 Nov 90 07:24:10 GMT
>Subject: Notes on Writing Portable Programs in C
>
>The eighth revision of `Notes on Writing Portable Programs in C'
>is now available.  The authors are A. Dolenc [ado@sauna.hut.fi],
>A. Lemmke, D. Keppel [pardo@cs.washington.edu], and
>G. V. Reilly [gvr@cs.brown.edu].
>

. . .

>
>The document can be obtained via anonymous FTP from sauna.hut.fi
>[130.233.251.253] in ~ftp/pub/CompSciLab/doc.  The files
>`portableC.tex', `portableC.sty', `portableC.bib', and
>`portableC.ps.Z' are the LaTeX source and style files, BibTeX and
>the compressed PostScript, respectively. Alternatively, there is a
>site in the US from which one can obtain all four files,
>cs.washington.edu [128.95.1.4] in ~ftp/pub/cport.tar.Z. All files
>are in the public domain.
>
>Comments, suggestions, flames, eggs, and requests for copies via
>e-mail should be directed to gvr@cs.brown.edu during December, and
>ado@sauna.hut.fi thereafter.
>

. . .

>George V. Reilly   `Wereduck'		gvr@cs.brown.edu   +1 (401) 863-7684
>uunet!brunix!gvr   gvr@browncs.bitnet	Box 1910, Brown U, Prov, RI 02912

--
/*******************************************************************************
** Jeff Biesiadecki               ** University of Illinois, Urbana-Champaign **
** jeffb@aquifer.geology.uiuc.edu ** Depts. of Geology and Computer Science   **
*******************************************************************************/

mike@odgate.odesta.com (Mike J. Kelly) (04/26/91)

An excellent book on portability is "Portable C" by Henry Rabinowitz and
Chaim Schaap.  Prentice-Hall, 1990.   It includes numerous examples and
a really good index to help you find recommendations/pitfalls on
particular areas.  It covers both machine portability problems, compiler
inconsistencies and general program style issues for easing
portablility.

sarima@tdatirv.UUCP (Stanley Friesen) (04/26/91)

In article <2573@plx.UUCP> ming@plxsun.uucp (Lak-Ming Lam) writes:
>I would like to develop program which can be portable to different system
>(e.g. PC/MS-DOS, UNIX, Mac OS, etc.).  I would like to have anyone of you
>help me on the following issues:
>
>o	what need to be aware of (e.g. word size, byte order, etc.)
Well, there are tremendous differences in these areas across machines.
However, depending on what you want to do, this may not be very significant.
For most types of applications it is possible to write very simple code
that does not depend on word size or byte ordering.  Generally, if you
avoid dealing with binary files and type punning you are fairly safe.

The main area to watch for otherwise is using bit masks. Never assume a
particular number of bits in a word when masking a particular bit off.
You can avoid this by using the '~' operator to generate the inverse mask.
For example:
#define BAD_BIT 4
...
flags &= ~BAD_BIT;	/* Turn off BAD_BIT	*/

Your *real* problem in the list of systems you gave is in the OS interface.
They are totally and utterly different.  You can (hopefully) rely on the
existance of something approximating the standard I/O library on all of the
systems mentioned.  But this is rarely adequate for any but the simplest
applications.  Thus if you need something other than basic character &
line oriented I/O and simple memory allocation, you may have problems.

>o	how to use one set of source code to support different systems
>	(using #if MSDOS etc. or some other ways)

The solution is two-fold.   First, try to isolate as much of the OS
interface as possible into as few low-level routines as possible.
Second, use #if and #define to customize the OS interface portion
as needed.

A 'standard' header file that contains standard OS specific definitions
is quite helpful.  You can use #define macros here to make the system
calls have a standard appearance across all machines (at least to some
degree - where they are sufficiently compatible).

A great deal depends on just what OS facilities you need to use, and
which C compilers you are using on each machine.
-- 
---------------
uunet!tdatirv!sarima				(Stanley Friesen)

mcdaniel@adi.com (Tim McDaniel) (04/26/91)

In article <1991Apr25.205236.21765@odgate.odesta.com>
mike@odgate.odesta.com (Mike J. Kelly) writes:

   An excellent book on portability is "Portable C" by Henry Rabinowitz and
   Chaim Schaap.  Prentice-Hall, 1990.

Like HELL it is!  The authors have a basic understanding of C, but
they miss, misrepresent, or state small inaccuracies about a lot of
points.  They also advocate practices that are unsafe in any language.
This book is dangerous, and a waste of $30.  It's far better to use
Andrew Koenig's "C Traps and Pitfalls" and Mark Horton's "Portable C
Programming".

The most glaring problem is section 9.10, "Porting other people's
code".  In its entirety:

   It is possible to post a large program written by others without
   understanding how it works.  At most, you may have to read some
   small sections of code.  Here is a step-by-step procedure that has
   proven effective in porting other people's code.

   1. Look at the makefile(s) for the code and adjust all
   environment-specific settings to fit your environment.

   2. Look at all the #ifs and #ifdefs in the code to make sure the
   flags are defined appropriately for your environment.

   3. Try to make the program.  Often, it will fail to compile.  Make
   the changes necessary to get it to compile and link.

   4. Lint the code.  Lint all the source files together if possible.
   Make appropriate changes in the code.

   5. Make the program again.

   6. Run the program.  If it dies, use a runtime checker for
   diagnosis, or as a last resort, use a debugger.  Repair the
   program, return to step 3, and repeat.

How do you even START to criticize that?!?

Another example, from page 7: They identify the problem with not
declaring strcat() in:
   
   #define VERSION "1.03"
   void prVersion();
   main()
   {
      prVersion();
      ...
   }
   
   void prVersion()
   {
      static char outmsg[20] = "Version #";
      printf(strcat(outmsg, VERSION));
   }

Hint: what goes wrong when you change the #define to one of these?
   #define VERSION "1.04 alpha (internal)"
   #define VERSION "90% of V2"

They advocate using both new-style and old-style function declarations
in header files (under __STDC__), but only old-style in functions.
The problem of default argument promotions is mentioned ONLY in a
too-brief footnote three pages later.

Floating-point zero should not be used in a Boolean context,
but one of the reasons is NOT that "floating-point zero may not be
all-bits zero in some environments"!

Their five pages on internationalization can't even scratch the
surface.  (This section was right after the "porting procedure" above;
perhaps the authors just got tired when writing that.)

page 140: "The only integer value than can be portably assigned to any
pointer is 0."  Wrong: only an integer constant expression evaluating
to 0 can be assigned.
   int i = 0;
   int *ip = i;
doesn't work.  In general, they don't seem to have a 100%
understanding of pointers and arrays -- but then again, they probably
haven't read Chris Torek.

Bascially, just use Koenig and Horton, and read everything that torek,
gwyn, scs, or ok post.  (I know I'm forgetting a few in that list ...)

--
   "Of course he has a knife; he always has a knife.  We all have knives.
   It's 1183 and we're barbarians."
Tim McDaniel                 Applied Dynamics Int'l.; Ann Arbor, Michigan, USA
Internet: mcdaniel@adi.com                UUCP: {uunet,sharkey}!amara!mcdaniel

torek@elf.ee.lbl.gov (Chris Torek) (04/27/91)

In article <MCDANIEL.91Apr26114620@dolphin.adi.com> mcdaniel@adi.com
(Tim McDaniel) writes:
>>... "Portable C" by Henry Rabinowitz and Chaim Schaap.  Prentice-Hall, 1990.
>
>... The authors have a basic understanding of C, but they miss,
>misrepresent, or state small inaccuracies about a lot of points.

(No comment here, since I have not read the book.)

>They also advocate practices that are unsafe in any language. ...
>The most glaring problem is section 9.10, "Porting other people's
>code".  [method mostly deleted: see parent article, or the book itself]
>
>   It is possible to post a large program written by others without
>   understanding how it works. ...
>
>How do you even START to criticize that?!?

The funny thing is that this technique often works.  It should, however,
be considered a last resort, to be used only when one is pressed for time.
Depending on the program, this `time-saving' method sometimes backfires
(one would do better to read and recode the program than debug it `inch
by inch', as it were).  If Rabinowitz and Schaap give it as `the' method,
this is indeed a disservice.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov