comp.lang.ada
 help / color / mirror / Atom feed
From: nabbasi@earthlink.net
Subject: Re: ifdef replacement for GNAT
Date: 1998/04/11
Date: 1998-04-11T00:00:00+00:00	[thread overview]
Message-ID: <6gn4q1$ee6@drn.newsguy.com> (raw)
In-Reply-To: dewar.892261504@merv


In article <dewar.892261504@merv>, dewar@merv.cs.nyu.edu says...

>The proper approach for achieving target dependence is to follow two steps
>
>  (a) encapsulte the target dependence down to the minimum level
>
>  (b) Provide separate target dependent units for these remaining functions
>

Prof. Dewar, let me try to see what you mean by point (a) above by 
an example (I am also one of those who learn better by examples, for no
other reason other than to be clear on what things mean):

Lets assume we have UNIX and VMS (for the purpose of this example). 

Lets assume one wants to create a child process. on UNIX one calls fork(), 
on VMS one calls vfork(). There are nowadays 3 main methods of how to
do this.

first solution
=============

cc -DUNIX program.c
 
program.c
+--------------------------------------+
| #if defined(VMS)                     |
|     status = vfork()                 |
| #else                                |
| #if defined(UNIX)                    |
|      status= fork()                  |
| #else                                |
| #error "unsupported platform"        |
| #endif /* UNIX */                    |
| #endif /* VMS */                     |
+--------------------------------------+

Now, I do not like the above myself, for the same reason you say, it also makes
the code hard to read and maintain.

second solution
================
The other approach is to do this:

cc -DUNIX program.c

program.c
+-----------------------------+
|#include "program.h"         |
|  status=  GENERIC_fork();   |
+-----------------------------+

program.h
+---------------------------------+
| #if defined(VMS)                |
| #define GENERIC_fork vfork      |
| #else                           |
| #if defined(UNIX)               |
| #define GENERIC_fork fork       |
| #else                           |
| #error "unsupported system"     |
| #endif                          |
| #endif                          |
+---------------------------------+

This above is a little better since the main source code is not cluttered, and
the ifdef stuff is kept in one header file, but it  also suffer from some of
the same problems. It also has an additional problem which is against 
the "what you see is what you get". i.e. one looks at the source code in
program.c, they do not know actually what the call will turn up to be 
without looking around in some other header files to find out.

(another variation on the above is to use a compiler directive (as in
-Dfork=vfork) to make replacement of all "fork" tokens to become "vfork".
This assumes that the original files used the fork call. This also is a bad
solution, as it is confusing and is not what you see is what you get when
looking at the code. but can be useful to eliminate the need to edit many
files manually or add ifdef everywhere where the call is made.

third solution
==============

have one file (package in Ada terms) that contains all the specific
platform functions that are not command to other platforms. so in the
above example we can have

    program.c                   VMS.c                    UNIX.c
+---------------------------+  +-------------------+   +---------------------+
|                           |  |#include "unistd.h"|   |#include "unistd.h"  |
| #include "program.h"      |  |int GENERIC_fork() |   | int GENERIC_fork()  |
| status = GENERIC_fork()   |  | {                 |   |{                    |
|                           |  |   return vfork(); |   |   return fork();    |
+---------------------------+  | }                 |   |}                    |
                               +-------------------+   +---------------------+

program.h
+--------------------------+
| int GENERIC_fork();      |
+--------------------------+

Now, this is better.


When on UNIX, the makefiles will link the common source code against
the UNIX specific files, and when on VMS the makefiles will be directed
to link against the VMS specific platform dependent file(s) as in:

on VMS:
cc -c VMS.c
cc program.c VMS.o

on UNIX:
cc -c UNIX.c
cc program.c UNIX.o

This solution I like the most of the three. first, the common source code
is free of ifdef stuff. and so easier to read and maintain. it also easy
to find where all the platform specific stuff is located. the platform
specific file(s) should also be named to reflect the platform, but this
is minor point.

The only problem with the third solution is that one needs to design
the program from the start with this in mind. i.e. any operation  which
could possibly be different on different platforms must be not called
directly from the "common" body of the program, but instead wrap it and
make the platform specific calls from the platform specific module(s).

many time, people do not do this (how many of us who code in c/c++ wraps
a fork() call for example? or an open() or etc..etc.., but later on,
when one wants to port the program to a different platform, and then find
out that that call is not exactly the same as on the first platform, the 
easy and the quickest way will be to resort to solution 1 above, 
in particular when the program needs to be done by Monday morning :)

I think the hardest thing is to foresee in advanced what the platform
specific calls will be. or what the platform specific components will be.

for example reading a directory file I do not think is available on windows
as is done on UNIX. and so this have to be wrapped (or abstracted).

I assume what you meant by point (a) is something along the lines of
the third solution above. right?

I am not sure about your point (b) above, since it seems to be folded into
(a), at least in the way I thought about (a). 

thanks,
Nasser




  reply	other threads:[~1998-04-11  0:00 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <352287EE.1CFB@tolstoy.mdc.com>
1998-04-08  0:00 ` ifdef replacement for GNAT John T Vegezzi 312C M 237110
1998-04-09  0:00   ` Robert Dewar
1998-04-10  0:00     ` Dirk Zoller
1998-04-10  0:00       ` Robert Dewar
1998-04-11  0:00         ` nabbasi [this message]
1998-04-11  0:00           ` Larry Kilgallen
1998-04-13  0:00           ` Richard Kenner
1998-04-11  0:00         ` raw
1998-04-11  0:00         ` Larry Kilgallen
1998-04-13  0:00         ` Michael F Brenner
1998-04-13  0:00           ` Larry Kilgallen
1998-04-15  0:00             ` Ada Programming Environment [was ifdef replacement for GNAT] Nick Roberts
1998-04-14  0:00         ` ifdef replacement for GNAT Jean-Pierre Rosen
1998-04-11  0:00       ` Geert Bosch
1998-04-12  0:00         ` Haug Buerger
1998-04-13  0:00           ` Aaro Koskinen
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox