[comp.lang.misc] Header files

new@udel.EDU (09/28/89)

One thing I have always liked about the C language was the separation
between the "header" files (.h) and the "code" files (.c).  In other
languages, such as Modula-II and (I think) Ada, it is not possible to
define multiple "implementation" modules for a single "definition"
module.  Note that I mean multiple implementation modules implementing
different parts of the same header module; I do not mean different
complete implementations of the same header module.  For example,
in C I can make one header file that defines the prototype information
for all the string functions.  I can then write each string function into
a different implementation file.  Thus, with one "include" (Import)
statement, I get all the declarations for all the string functions.
However, the linker only links in the functions I use.  As another
example, all the file stuff is in "stdio.h".  However, it can be
implemented with open, read, write, close, and delete in five different
code files, allowing me to avoid loading the writing code if I don't write,
allowing me to link the open/close in one overlay and the read/write
in another overlay, and allowing me to avoid recompiling the entire
I/O library when making a change to just one routine. I know of no
other compiled language defined in this way (except, of couse, C++).

This would be less of an issue if linkers or compilers were smart
enough to only include the functions from a single module that were
actually used and if we all had demand-paged VM.  Even this, however,
would not solve the "recompile everything" problem.  I know very little
Ada, but it seems to me that I've not heard of this ability in Ada.

Does anyone know of any relatively popular languages that allow this
sort of separation other than C and C++?  If not, why not? Discussion?

				 -- Darren

billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ) (09/28/89)

From article <24955@louie.udel.EDU>, by new@udel.EDU:
> [Header files idea]
> This would be less of an issue if linkers or compilers were smart
> enough to only include the functions from a single module that were
> actually used and if we all had demand-paged VM.  Even this, however,
> would not solve the "recompile everything" problem.  I know very little
> Ada, but it seems to me that I've not heard of this ability in Ada.

   Try the Telesoft TeleGen2 compiler.  If you want the really serious
   details of how extensive the optimization is in this compiler, take
   a look at the Tri-Ada '88 proceedings; I believe there are several
   articles just on this one compiler's heavy-duty optimization strategies. 

   This particular optimization is almost essential if one is to properly
   support ADTs (one of the things Ada is really good at doing), since
   the user will almost never use all of the ADT services provided.  It
   would really be kind of ridiculous NOT to trim away the extra code.

   As far as recompilation is concerned, you can make use of Ada's
   separate compilation facility to achieve this directly.  I don't
   do this because it would be a pain to have things scattered into
   umpteen different files, and I have no idea why you would consider
   this to be desirable. 


   Bill Wolfe, wtwolfe@hubcap.clemson.edu

jdarcy@multimax.encore.com (Jeff d'Arcy) (09/28/89)

billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ):
>    As far as recompilation is concerned, you can make use of Ada's
>    separate compilation facility to achieve this directly.  I don't
>    do this because it would be a pain to have things scattered into
>    umpteen different files, and I have no idea why you would consider
>    this to be desirable. 

When you have multiple software engineers working on the same major
component, smaller files reduce contention for the sources, which
(quite obviously) can improve overall productivity.

Jeff d'Arcy		jdarcy@encore.com		(508) 460-0500
    Encore has provided the medium, but the message remains my own

chase@Ozona.orc.olivetti.com (David Chase) (09/28/89)

In article <24955@louie.udel.EDU> new@udel.EDU (Darren New) writes:
>One thing I have always liked about the C language was the separation
>between the "header" files (.h) and the "code" files (.c).  In other
>languages, such as Modula-II and (I think) Ada, it is not possible to
>define multiple "implementation" modules for a single "definition"
>module.

>Does anyone know of any relatively popular languages that allow this
>sort of separation other than C and C++?  If not, why not? Discussion?

Modula-3 allows this separation (popular?).  It's a bit of a pain,
actually, since there's (for the moment) data structures which need
initialization at run-time.  Given, say "MODULE A EXPORTS B", it isn't
really clear whether or not the code generated for this module should
initialize the data structures for B, since there might also be some
MODULE C exporting B.  These run-time structures are required because
Modula-3(revised unpublished report) has Neat New Features like
"opaque supertypes" (that's a supertype, but you don't know how many
methods it has or what or how large the fields are) and constants of
types exported by "required interfaces" (meaning that the constant is
initialized at *run time* by the implementation of the required
interface) and default field values for allocated records and objects
(even for the fields in the opaque supertype).

What we do now is generate the init code in all possible exporters;
typically the number of exporters is small, so this doesn't kill us,
but it isn't wonderful.  The pre-linker is getting smarter too, so in
several cases the redundant code is generated, but not executed.

Still, it is a hassle.  Several things would be easier if (a) we
weren't generating C as an intermediate language and (b) the Unix
linker (SunOS 3.5, and apparently also 4.0) wasn't quite as dumb as a
rock.

David

billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe, 2847 ) (09/28/89)

From jdarcy@multimax.encore.com (Jeff d'Arcy):
>>    As far as recompilation is concerned, you can make use of Ada's
>>    separate compilation facility to achieve this directly.  I don't
>>    do this because it would be a pain to have things scattered into
>>    umpteen different files, and I have no idea why you would consider
>>    this to be desirable. 
> 
> When you have multiple software engineers working on the same major
> component, smaller files reduce contention for the sources, which
> (quite obviously) can improve overall productivity.

   The basic Ada strategy is to divide things into various packages
   (for example, each ADT would have its own package).  Now since 
   the implementation of a package can be recompiled without any
   recompilation of anything depending on the package's specification,
   there is no source code contention if one person is assigned to a
   given package, which is generally the case.  If a package is too
   big for one person to handle, it most likely should be rethought
   and broken down into more than one package.

   One could also use separate compilation to take the separation
   down to the level of each procedure or function within the
   package, but this is really going hog-wild.  At this point,
   the hassle of trying to locate source files exceeds any benefit
   which might exist, and since a package is intended to be a very
   manageable unit there wouldn't be any real benefit anyway. 


   Bill Wolfe, wtwolfe@hubcap.clemson.edu

nick@lfcs.ed.ac.uk (Nick Rothwell) (09/28/89)

In article <24955@louie.udel.EDU>, new@udel writes:
>One thing I have always liked about the C language was the separation
>between the "header" files (.h) and the "code" files (.c).

>Does anyone know of any relatively popular languages that allow this
>sort of separation other than C and C++?  If not, why not?
Discussion?

ML can do the same sort of thing:

	signature SMALL_PART =
	  sig
	    type ... and ... and ...
	    val ... : ty1 and ... : ty2 and ...
	  end;

	signature ANOTHER_SMALL_PART = ...

	signature ENTIRE_THING =
	  sig
	    include SMALL_PART
	    include ANOTHER_SMALL_PART
	  end

This gives you inclusion of interfaces. There's also nesting of
interfaces; the ENTIRE_THING signature could specify two sub-modules
with smaller signatures. The actual module to match ENTIRE_THING could
be a single object containing all the type specs and functions, or
could be built from two (or more) separate ones:

	functor EntireThing(structure Part1: SMALL_PART
			    structure Part2: ANOTHER_SMALL_PART
			   ) =
	  struct
	    open Part1		(* simple case: inclusion. *)
	    open Part2
	  end;

You can also have several implementations maching the same interface
of course (but you said you weren't interested in that).

>				 -- Darren

		Nick.
--
Nick Rothwell,	Laboratory for Foundations of Computer Science, Edinburgh.
		nick@lfcs.ed.ac.uk    <Atlantic Ocean>!mcvax!ukc!lfcs!nick
~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~
               Fais que ton reve soit plus long que la nuit.

wright@hsi.UUCP (Gary Wright) (09/28/89)

In article <24955@louie.udel.EDU> new@udel.EDU (Darren New) writes:
>Does anyone know of any relatively popular languages that allow this
>sort of separation other than C and C++?  If not, why not? Discussion?

Eiffel does not have use header files but does support separate
compliation.  Each eiffel class resides in its own file.  An individual
class may be compiled or an entire system of classes may be compiled.
To create an executable, one class is designated as the root class.
Starting at the root class, the compiler examines the heirarchy of
dependancies and recompiles any classes that have changed or that use
another class whose *interface* has changed (if only the implementation
has changed, not the interface, then clients of that class need not be
recompiled).  The compiler handles any client cycles automatically.

There is no need to play games to avoid including header files more than once,
building make file dependencies, or waiting until link time to find all
the pieces of a class.
-- 
Gary Wright 					...!uunet!hsi!wright
Health Systems International                    wright@hsi.com

bga@odeon.ahse.cdc.com (Bruce Albrecht) (09/29/89)

In article <24955@louie.udel.EDU>, new@udel.EDU writes:
> One thing I have always liked about the C language was the separation
> between the "header" files (.h) and the "code" files (.c).  ...
> Does anyone know of any relatively popular languages that allow this
> sort of separation other than C and C++?  If not, why not? Discussion?

I will probably have several people tell me I'm wrong about this, but 
#include is a directive for the c pre-processor and not part of the language
itself.  The implication of this, therefore, is that if you have a preprocessor
for your favorite language, you can do this with any language that supports
separately compiled modules.

loren@rutabaga.Rational.COM (Loren Rosen) (09/29/89)

You can do more or less what you want in Ada, through the use of separate
subprograms.  Also, many of the production Ada compilers will remove
code for unused subprograms from the executable.

Header files have drawbacks of their own.  It's all too easy in a large
system to try to load two things that have the same name, or leave something
out.  You don't find out until the loader complains about multiply-defined
or undefined names.

--
     -- Loren Rosen, the token irrationalist at ...
	    Rational, 3320 Scott Blvd. Santa Clara Ca. 95054
            loren@rational.com  uunet!igor!loren

dor@lanl.gov (David O. Rich) (09/29/89)

 In article <24955@louie.udel.EDU>, new@udel.EDU writes:
 > One thing I have always liked about the C language was the separation
 > between the "header" files (.h) and the "code" files (.c).  ...
 > Does anyone know of any relatively popular languages that allow this
 > sort of separation other than C and C++?  If not, why not? Discussion?
 
Yup, Modula-2.  A program can be decomposed into a set of DEFINITION and
corresponding IMPLEMENTATION modules.  For details (opinions, etc) try
comp.lang.modula2.

--dave

johnl@esegue.segue.boston.ma.us (John R. Levine) (09/29/89)

In article <2427@odeon.ahse.cdc.com> bga@odeon.ahse.cdc.com (Bruce Albrecht) writes:
>I will probably have several people tell me I'm wrong about this, but 
>#include is a directive for the c pre-processor and not part of the language
>itself.  ...

Don't confuse the language with the implementation you happen to use.  On
most unix systems the # directives are handled by a separate pass before the
rest of the compiler, but there are lots of versions where it's all done in
one pass.  The ANSI C standard says quite a lot about what preprocessor
actions are supposed to do without saying anything about how they're
supposed to be implemented.
-- 
John R. Levine, Segue Software, POB 349, Cambridge MA 02238, +1 617 492 3869
johnl@esegue.segue.boston.ma.us, {ima|lotus}!esegue!johnl, Levine@YALE.edu
Massachusetts has 64 licensed drivers who are over 100 years old.  -The Globe

bschwart@elbereth.rutgers.edu (dare-gale skylark) (10/07/89)

In article <2427@odeon.ahse.cdc.com> bga@odeon.ahse.cdc.com (Bruce Albrecht) writes:
>I will probably have several people tell me I'm wrong about this, but 
>#include is a directive for the c pre-processor and not part of the language
>itself.  The implication of this, therefore, is that if you have a preprocessor
>for your favorite language, you can do this with any language that supports
>separately compiled modules.

(a)  The new C standard will make '#include' part of the language definition.

(b)  This does not prevent a crafty person from running his sources
     through cpp (or m4 or another macroprocessor) before compiling.
     There isn't even a compatibility problem, because you hand out
     the macroprocessed sources instead of the originals.

     The authors of sendmail configuration files figured out a long
     time ago that you can use a macroprocessor outside of C programming.



-- 
Barry Schwartz, Chief SAPsucker                  bbs@cdspr.rutgers.edu
Grad Student, Dept. of Elec. and Comp. Engg.     bschwart@elbereth.rutgers.edu
Rutgers University College of Engg.              bbs@hankel.rutgers.edu
Piscataway, NJ 08854    U.S.A.                   rutgers!cdspr!bbs