comp.lang.ada
 help / color / mirror / Atom feed
* Preprocessor functionality equivalent ideas needed
@ 2003-12-10 20:04 Greg Milford
  2003-12-10 21:41 ` Ludovic Brenta
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Greg Milford @ 2003-12-10 20:04 UTC (permalink / raw)


Hello

I checked the FAQ for this group and did not get an answer to this.  I know
Ada does not have a preprocessor, so how should I go about maintaining
changes to a common code base that needs to be built under two different
configurations?

Am I left with using Global variables or has a better method been used?  I
am new to Ada so be kind :)

Greg





^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preprocessor functionality equivalent ideas needed
  2003-12-10 20:04 Greg Milford
@ 2003-12-10 21:41 ` Ludovic Brenta
  2003-12-10 22:29 ` Georg Bauhaus
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Ludovic Brenta @ 2003-12-10 21:41 UTC (permalink / raw)


"Greg Milford" <gregory.a.milford@boeing.com> writes:

> Hello
> 
> I checked the FAQ for this group and did not get an answer to this.  I know
> Ada does not have a preprocessor, so how should I go about maintaining
> changes to a common code base that needs to be built under two different
> configurations?
> 
> Am I left with using Global variables or has a better method been used?  I
> am new to Ada so be kind :)
> 
> Greg

GNAT does have a preprocessor called gnatprep, but it is not part of
the language standard.  If you cannot or won't use it, the usual way
to deal with configuration management issues such as you describe is
to write two or more different bodies for a single package
specification, and let the build scripts (Makefiles or such) compile
one or the other for each particular configuration.  Of course, you'll
want to isolate all configuration-dependent stuff into a separate
package which you keep as small as possible; this is usual software
engineering practice.

There are various ways to achieve this.  For example, assume you have:

a.ads   the package specification
a1.adb  package body for target 1
a2.adb  package body for target 2

Your makefiles could select one of the *.adb files and symlink it to
a.adb; then the compiler finds the proper file and compiles it.  This
is in fact the approach used by GNAT itself.

Another approach could be to simulate a preprocessor with sed or perl
scripts.

HTH

-- 
Ludovic Brenta.



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preprocessor functionality equivalent ideas needed
  2003-12-10 20:04 Greg Milford
  2003-12-10 21:41 ` Ludovic Brenta
@ 2003-12-10 22:29 ` Georg Bauhaus
  2003-12-12  5:52   ` Simon Wright
  2003-12-11  1:07 ` Jeffrey Carter
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Georg Bauhaus @ 2003-12-10 22:29 UTC (permalink / raw)


Greg Milford <gregory.a.milford@boeing.com> wrote:
: Hello
: 
: I checked the FAQ for this group and did not get an answer to this.  I know
: Ada does not have a preprocessor, so how should I go about maintaining
: changes to a common code base that needs to be built under two different
: configurations?
: 
: Am I left with using Global variables or has a better method been used?  I
: am new to Ada so be kind :)

If configurations also refers to changes to effective source code
adapted to some (perhaps OS-) specifics, read on, otherwise please
forgive the many words.

As with a preprocessor, you can exchange parts of the program (a
package body for example, or a function body, ...), and the other
parts of the program do not have to be changed. But this can be
done by supplying one or another implemention to the compiler as a
compilation unit for the part in question. The tools will help, for
example by looking for program units in different configuration
specific directories.

But you can also use the language feature "renaming".

For the sake of an example, if you specify the function

function add_one (n: Natural) return Natural;
--  result = n + 1

and you might want to provide different implementations
(just as if you wanted the same function call to work in different
configurations, with the implementation changed).
One implementation of what is specified with add_one might be

   function add_one_using_plus (n: Natural) return Natural is
   begin
      return n + 1;
   end add_one_using_plus;

Another might use the 'Succ attribute of type Natural:

   function add_one_using_succ (n: Natural) return Natural is
   begin
      return Natural'succ(n);
   end add_one_using_succ;

What remains to do is to choose one of these implementions as
implementation for add_one. This can be done writing

   function add_one (n: Natural) return Natural
     renames add_one_using_plus;

(or
   function add_one (n: Natural) return Natural
     renames add_one_using_succ;
if you want the other implementation).

If some other part of your program now has "add_one(42)", 
the implementation of the renaming will be in effect.
However, one does not have to do that for each and every system
specific subprogram.

Instead you could collect the specifications of procedures and
functions that are likely to be system dependent in a package
called something like Operating_System_Specific. Then, you
create packages for Windows, Mac, Unix, VMS, whatever, providing
the same subprograms, adapted for each OS (or configuration, if
that requires different implementations). In order to use system
dependent subprograms, the rest of your program only needs to know
about the package Operation_System_Specific. (That is, you write
"with Operating_System_Specific;" before program units that need this
package's subprograms, no matter on what OS/configuration the program
is to run.)

Then rename the package written for the target operating system.
This time the "renames" will apply (sort of) to what is in the
packages, collectively.

with Windows_Specific;
package Operating_System_Specific renames Windows_Specific;

Now the program units that "with Operating_System_Specific;" will
effectively use the facilities of package Windows_Specific without
"knowing" this.
If you want your program to run on Unix, the only change would be

with Unix_Specific;
package Operating_System_Specific renames Unix_Specific;

in place of the two lines above.

There are two more ways I know of, one uses generics for listing
the configuration-specific things that your program needs. The other
uses tagged types, that is O-O types. Again for OSs,

generic
   type OS is private;

   with function available_disk_space (op_sys: OS) return Natural;
   --  free blocks

package System_Dependent is
   procedure Installation_Setup;
   procedure Unpack;
end System_Dependent;

If you now write

with BSD;
package Everywhere_Working_Installation is
  new Specifics (available_disk_space => BSD.free_blocks_count);

you can use the procedures in package Everywhere_Working_Installation
in your program.

The O-O type:

package Installation is

   type OS is abstract tagged private;
   --  an operating system abstraction

   procedure Installation_Setup(op_sys: OS) is abstract;
   procedure Unpack(op_sys: OS) is abstract;

private
   type OS is abstract tagged
      record
        --  ...
      end record;

end Installation;

You derive new concrete types from OS,

   type Windows is new OS with private;

and override the two procedures to work with Windows:

   procedure Installation_Setup(op_sys: Windows);
   procedure Unpack(op_sys: Windows);

After that you can have a variable (or constant) of one of the derived
types,

   my_system: Unix;

and from here onwards use the procedures defined with the type.
The correct version of Installation_Setup and Unpack will be chosen
depending on what type my_system actually is, and the translation
tools need not link the overriden procedures for other OSs.


If you are out for more, you can combine these methods (and
possibly more) :-)

my 2c

-- Georg




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preprocessor functionality equivalent ideas needed
  2003-12-10 20:04 Greg Milford
  2003-12-10 21:41 ` Ludovic Brenta
  2003-12-10 22:29 ` Georg Bauhaus
@ 2003-12-11  1:07 ` Jeffrey Carter
  2003-12-11 13:34   ` Marin David Condic
  2003-12-11  5:39 ` Steve
  2003-12-11 16:59 ` Martin Krischik
  4 siblings, 1 reply; 11+ messages in thread
From: Jeffrey Carter @ 2003-12-11  1:07 UTC (permalink / raw)


Greg Milford wrote:

> I checked the FAQ for this group and did not get an answer to this.  I know
> Ada does not have a preprocessor, so how should I go about maintaining
> changes to a common code base that needs to be built under two different
> configurations?

Generally, you define a package specification for the functionality you 
require, then implement different bodies for it for the different 
situations.

-- 
Jeff Carter
"Perfidious English mouse-dropping hoarders."
Monty Python & the Holy Grail
10




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preprocessor functionality equivalent ideas needed
  2003-12-10 20:04 Greg Milford
                   ` (2 preceding siblings ...)
  2003-12-11  1:07 ` Jeffrey Carter
@ 2003-12-11  5:39 ` Steve
  2003-12-11 16:59 ` Martin Krischik
  4 siblings, 0 replies; 11+ messages in thread
From: Steve @ 2003-12-11  5:39 UTC (permalink / raw)


Support for multiple configurations is not built into the language, but many
development environments do.  What development environment are you using?

Steve
(The Duck)


"Greg Milford" <gregory.a.milford@boeing.com> wrote in message
news:Hpp3r9.6L0@news.boeing.com...
> Hello
>
> I checked the FAQ for this group and did not get an answer to this.  I
know
> Ada does not have a preprocessor, so how should I go about maintaining
> changes to a common code base that needs to be built under two different
> configurations?
>
> Am I left with using Global variables or has a better method been used?  I
> am new to Ada so be kind :)
>
> Greg
>
>





^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: Preprocessor functionality equivalent ideas needed
@ 2003-12-11 12:52 Lionel.DRAGHI
  0 siblings, 0 replies; 11+ messages in thread
From: Lionel.DRAGHI @ 2003-12-11 12:52 UTC (permalink / raw)
  To: comp.lang.ada



| -----Message d'origine-----
| De: Steve [mailto:nospam_steved94@comcast.net]
..
| Support for multiple configurations is not built into the 
| language, but many
| development environments do.


If just considering build time configuration, my experience is that you
should consider in this order:
1 - programmming possibilities. As statted by Georg Bauhaus, there are many
way to manage multiple configurations at langage level, with idioms or
design patterns. This is the best way because the compiler is the the more
reliable way to build and check a configuration.

2 - sources selection : you need to select the right sources for each
configuration. Note that this is pretty unavoidable even when using idioms
and patterns.

3 - sources modification : macro-generation, preprocessing, etc. It's some
time hard to avoid, but sources will be less readable, build is less
straightforward, and most of the tools will no more understand the sources,
as those are no more Ada. 
For example, if you use GNAT preprocessor, you will depend on GPS to read
the sources, or fall back on whatever simple text editor. If you use your
own preprocessor, it's even worse.

So, I recommand you to consider programming way before development
environments.

-- 
Lionel Draghi



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preprocessor functionality equivalent ideas needed
  2003-12-11  1:07 ` Jeffrey Carter
@ 2003-12-11 13:34   ` Marin David Condic
  2003-12-11 17:49     ` Jeffrey Carter
  0 siblings, 1 reply; 11+ messages in thread
From: Marin David Condic @ 2003-12-11 13:34 UTC (permalink / raw)


While I agree with the general concept of separate bodies for separate 
implementation-specific modules, I have occasionally run into situations 
where it would have been nice if I had a compiler directive of some sort 
to go one way or another depending on some condition. This is especially 
true where I might need to keep code portable between two different 
compilers. Also its a big problem when what needs to be different is in 
the *specification* of something. (Yes, I know, "One more layer of 
indirection...." can go fix it - but why should it be so hard?)

Maintaining two sets of files has a problem - its two sets of files! :-) 
You change something in one file & you have to remember to make the 
update to the other one. You want to give the code off to someone else, 
you thus have to supply both sets of files and sufficient information to 
enable them to build it either way. Someone unaware of the parallel 
paths can really mess things up. Some sort of conditional compilation 
can simplify matters. (The existence of pragma Assert and pragma Debug 
in the Gnat compiler attest to at least *some* usefulness to conditional 
compilation.)

I have sometimes been able to simulate conditional compilation by 
putting code into an if statement with a constant flag. Some compilers 
will optimize away the unreachable code. But that doesn't help much in 
declarative parts or in situations where a set of statements is 
acceptable to one compiler, but not another. I'd hate to see Ada develop 
into the unholy mess that C is with all of its macros and other 
confusing garbage, but maybe a couple of pragmas that let alternate 
versions of the code exist within a single file might not be a bad thing?

MDC

Jeffrey Carter wrote:
> 
> 
> Generally, you define a package specification for the functionality you 
> require, then implement different bodies for it for the different 
> situations.
> 


-- 
======================================================================
Marin David Condic
I work for: http://www.belcan.com/
My project is: http://www.jsf.mil/NSFrames.htm

Send Replies To: m   o   d   c @ a   m   o   g
                    c   n   i       c   .   r

     "Trying is the first step towards failure."
         --  Homer Simpson

======================================================================




^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: Preprocessor functionality equivalent ideas needed
@ 2003-12-11 15:51 Lionel.DRAGHI
  0 siblings, 0 replies; 11+ messages in thread
From: Lionel.DRAGHI @ 2003-12-11 15:51 UTC (permalink / raw)
  To: comp.lang.ada



| -----Message d'origine-----
| De: Marin David Condic [mailto:nobody@noplace.com]
| This is especially 
| true where I might need to keep code portable between two different 
| compilers. Also its a big problem when what needs to be 
| different is in 
| the *specification* of something. (Yes, I know, "One more layer of 
| indirection...." can go fix it - but why should it be so hard?)

The whole point is what is harder, pre-processing or redesign?
I don't think there is a unique generic answer, but I observe that
pre-processing is often choosen because it's easier to settle down in the
*short term* than some redesign.  

-- 
Lionel Draghi



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preprocessor functionality equivalent ideas needed
  2003-12-10 20:04 Greg Milford
                   ` (3 preceding siblings ...)
  2003-12-11  5:39 ` Steve
@ 2003-12-11 16:59 ` Martin Krischik
  4 siblings, 0 replies; 11+ messages in thread
From: Martin Krischik @ 2003-12-11 16:59 UTC (permalink / raw)


Greg Milford wrote:

> Hello
> 
> I checked the FAQ for this group and did not get an answer to this.  I
> know Ada does not have a preprocessor, so how should I go about
> maintaining changes to a common code base that needs to be built under two
> different configurations?
> 
> Am I left with using Global variables or has a better method been used?  I
> am new to Ada so be kind :)

Some compilers do provide a preprocessor. GNAT for expample. Differenz to C
ist that GNAT writes the file to the disk. Well an extra file to take up
space but very handy when it comes to debugging.

Also, you can distribute the preprocessed file to those ada users without.

If you don't use GNAT you might want to take a look at AdaCL which comes
with a Text search an replace Library powerfull enough to convert normal
booch components into booch components for indefinite elements.

Last not least: Most c compiler can be told to just do the preprocessing and
then output there results into a file.

With Regards

Martin

-- 
mailto://krischik@users.sourceforge.net
http://adacl.sourceforge.net




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preprocessor functionality equivalent ideas needed
  2003-12-11 13:34   ` Marin David Condic
@ 2003-12-11 17:49     ` Jeffrey Carter
  0 siblings, 0 replies; 11+ messages in thread
From: Jeffrey Carter @ 2003-12-11 17:49 UTC (permalink / raw)


Marin David Condic wrote:

> While I agree with the general concept of separate bodies for separate 
> implementation-specific modules, I have occasionally run into situations 
> where it would have been nice if I had a compiler directive of some sort 
> to go one way or another depending on some condition. This is especially 
> true where I might need to keep code portable between two different 
> compilers. Also its a big problem when what needs to be different is in 
> the *specification* of something. (Yes, I know, "One more layer of 
> indirection...." can go fix it - but why should it be so hard?)

There are several ways to deal with needing multiple versions of the 
spec. Sometimes you can use functions instead of constants:

package P is -- Version X
    Num_Processors : constant := 4;
end P;

package P is -- Version Y
    Num_Processors : constant := 256;
end P;

becomes

package P is
    function Num_Processors return Positive;
end P;

Functions are sometimes not acceptable because the value needs to be static.

Sometimes you can have multiple versions with different names, and use 
renaming to select the appropriate one:

package P_X is
    Num_Processors : constant := 4;

    Directory_Separator : constant Character := '\';
end P_X:

package P_Y is

    Num_Processors : constant := 256;

    Directory_Separator : constant Character := '/';
end P_Y;

with P_X;
package P renames P_X;

Now the values in P are static.

And while another layer of information hiding may be harder in the short 
run, it's almost always easier in the long run.

-- 
Jeff Carter
"Sir Lancelot saves Sir Gallahad from almost certain temptation."
Monty Python & the Holy Grail
69




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preprocessor functionality equivalent ideas needed
  2003-12-10 22:29 ` Georg Bauhaus
@ 2003-12-12  5:52   ` Simon Wright
  0 siblings, 0 replies; 11+ messages in thread
From: Simon Wright @ 2003-12-12  5:52 UTC (permalink / raw)


Georg Bauhaus <sb463ba@l1-hrz.uni-duisburg.de> writes:

> There are two more ways I know of, one uses generics for listing
> the configuration-specific things that your program needs. The other
> uses tagged types, that is O-O types. Again for OSs,
> 
> generic
>    type OS is private;
> 
>    with function available_disk_space (op_sys: OS) return Natural;
>    --  free blocks
> 
> package System_Dependent is
>    procedure Installation_Setup;
>    procedure Unpack;
> end System_Dependent;
> 
> If you now write
> 
> with BSD;
> package Everywhere_Working_Installation is
>   new Specifics (available_disk_space => BSD.free_blocks_count);
> 
> you can use the procedures in package Everywhere_Working_Installation
> in your program.

A technique we've found handy is an extension of the "generic
signature package" idea, for use when your code won't be written in a
generic:

generic
   with procedure Actual_P (I : Integer);
   with function Actual_Q return Boolean;
package Signature is
   procedure P (I : Integer) renames Actual_P;
   function Q return Boolean renames Actual_Q;
end Signature;

That way you don't have to use the names P, Q in the actual package
(indeed, the actual subprograms could come from more than one
package).

-- 
Simon Wright                               100% Ada, no bugs.



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2003-12-12  5:52 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-12-11 12:52 Preprocessor functionality equivalent ideas needed Lionel.DRAGHI
  -- strict thread matches above, loose matches on Subject: below --
2003-12-11 15:51 Lionel.DRAGHI
2003-12-10 20:04 Greg Milford
2003-12-10 21:41 ` Ludovic Brenta
2003-12-10 22:29 ` Georg Bauhaus
2003-12-12  5:52   ` Simon Wright
2003-12-11  1:07 ` Jeffrey Carter
2003-12-11 13:34   ` Marin David Condic
2003-12-11 17:49     ` Jeffrey Carter
2003-12-11  5:39 ` Steve
2003-12-11 16:59 ` Martin Krischik

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