[comp.lang.c++] Managing C/C++ Libraries: Dependencies

dave@lethe.UUCP (David Collier-Brown) (11/13/88)

> In article <124300001@inmet> stt@inmet writes:
>>A simple language extension would be:
>>
>>#include_once "classname.h"
[definition of include_once as equivalent to
 #ifdef classname_h
 #  include "classname.h"
 #  define classname_h
 #endif
]

From article <8387@nlm-mcs.arpa>, by mjr@vax2.nlm.nih.gov.nlm.nih.gov (Marcus J. Ranum):
> 	I wonder how much code would break is such an extension were added,
> and the #include_once were made the DEFAULT rather than the exception ? 

  I suspect very little: I used such a construct in a preprocessor
for multiple languages without further thought, and my C programs
tend to work correctly (they may, in fact, therefor be incorrect
:-). I'm crossposting the question to comp.lang.c for further
discussion.

 Ok, people! Would this change, made silently, injure correct
programs?  It is admitted that it may allow incorrect programs to
compile, but that isn't waht I'm concerned about.
  Specifically, what about include trees which cannot be tsorted?

--dave c-b

dave@lethe.UUCP (David Collier-Brown) (11/13/88)

  In the previous posting, s/ifdef/ifndef/ 
Sorry! Fingers on, logic off.

--dave

gsf@ulysses.homer.nj.att.com (Glenn Fowler[eww]) (11/14/88)

In article <3414@geaclib.UUCP>, dave@lethe.UUCP (David Collier-Brown) writes:
> > In article <124300001@inmet> stt@inmet writes:
> >>A simple language extension would be:
> >>
> >>#include_once "classname.h"
> [definition of include_once as equivalent to
>  #ifdef classname_h
>  #  include "classname.h"
>  #  define classname_h
>  #endif
> ]
#include_once is fundamentally different from #ifndef...#endif:

	#include_once	idempotency controlled by includer
	#ifndef...	idempotency controlled by includee

an include file intended to be included more than once is usually
written as such, so #include_once seems to be placing the control
in the wrong place

from an efficiency viewpoint, though, #include_once may be a win since
the include file contents need not be scanned

taking this into account, an experimental preprocessor, used by some
internal development organizations, has been doing the following
for the past year with no problems (other than stretching the dpANSI C
#include ``implementation defined'' meaning):

(1)	by default each #include file is included only once
(2)	a run time option forces the old behavior
(3)	a file to be included more than once must contain the statement
	``#pragma pp:multiple'' that is evaluated during the first include

comments:

(1)	how are files identified? does "x" == <x>, does "./x" == "x",
	with symlinks and ``ln -s a b'', does "a" == "b" (note that
	<dev,ino> is not a valid identity check on some distributed
	file system implementations)
(3)	pick your favorite #pragma syntax

this mechanism allows one to write headers in a dpANSI C comforming
manner while still exploiting efficient pp implementations:

(a)	idempotent include files are wrapped with #ifndef...#endif
(b)	multiply included headers contain ``#pragma pp:multiple''
-- 
Glenn Fowler    (201)-582-2195    AT&T Bell Laboratories, Murray Hill, NJ
uucp: {att,decvax,ucbvax}!ulysses!gsf       internet: gsf@ulysses.att.com

shap@polya.Stanford.EDU (Jonathan S. Shapiro) (11/15/88)

In article <3414@geaclib.UUCP> geaclib!lethe!dave writes:
>> In article <124300001@inmet> stt@inmet writes:
>>>A simple language extension would be:
>>>
>>>#include_once "classname.h"
>[definition of include_once as equivalent to
> #ifdef classname_h
> #  include "classname.h"
> #  define classname_h
> #endif
>]
> Ok, people! Would this change, made silently, injure correct
>programs?  It is admitted that it may allow incorrect programs to
>compile, but that isn't waht I'm concerned about.
>
>--dave c-b

That misses the point.  There is already a mechanism in place to do
this sort of thing (described above).  The danger of inserting
features like this is that they constrain future options for the
language.

The ANSI committee, as I recall, at one point debated having #include
work this way.  I don't recall the resolution, but it was a lousy
idea. Being able to reinclude files is useful. Your idea wouldn't
break that, but would introduce some unsual stuff that clearly isn't
necessary.

Further, #include_once puts the onus in the wrong place.  The decision
should be up to the included file, not the includer.  This frees the
include-file implementor to change the implementation transparently to
your code.

Jon

daveb@llama.rtech.UUCP (Dave Brower) (11/15/88)

In article <3414@geaclib.UUCP> geaclib!lethe!dave writes:
>>>#include_once "classname.h"

>From article <8387@nlm-mcs.arpa>, by mjr@vax2.nlm.nih.gov.nlm.nih.gov (Marcus J. Ranum):
>> 	I wonder how much code would break is such an extension were added,
>> and the #include_once were made the DEFAULT rather than the exception ? 
>
> Ok, people! Would this change, made silently, injure correct
>programs?  It is admitted that it may allow incorrect programs to
>compile, but that isn't waht I'm concerned about.
>  Specifically, what about include trees which cannot be tsorted?

Well, it will certainly break this year's Obfuscated C contest winner,
which calulated prime numbers in the preprocessor with use of multiple
inclusion and defined/undefed state variables.  Some might say it is
not a "proper" program, but it falls within the letter of the existing
and proposed laws.

-dB
"You have to run twice as fast to get anywhere" - Ben Johnson.
{amdahl, cpsc6a, mtxinu, sun, hoptoad}!rtech!daveb daveb@rtech.com

coggins@proline.cs.unc.edu (Dr. James Coggins) (11/15/88)

In article <5044@polya.Stanford.EDU> shap@polya.Stanford.EDU (Jonathan S. Shapiro) writes:
>Further, #include_once puts the onus in the wrong place.  The decision
>should be up to the included file, not the includer.  This frees the
>include-file implementor to change the implementation transparently to
>your code.
>
>Jon

I consider a library to be a single entity - a particularly appropriate
assumption in C++ due to the massive interdependencies.  I want the
Library to control how its files are #included, which is what the
scheme I originally presented accomplished.  It also removed concerns
about directory structures and file names from the domain of the
library coder by isolating such administrative concerns outside the code.

I hope you folks can decide something to do about cpp that would make
my whole scheme superfluous.  Until then, it works.

---------------------------------------------------------------------
Dr. James M. Coggins          coggins@cs.unc.edu
Computer Science Department   Working code is EXTREMELY valuable.
UNC-Chapel Hill               That's why ditzy prototypes tend to
Chapel Hill, NC 27514-3175    be difficult to throw away.
---------------------------------------------------------------------

jgm@k.gp.cs.cmu.edu (John Myers) (11/17/88)

In article <3414@geaclib.UUCP> geaclib!lethe!dave writes:
>From article <8387@nlm-mcs.arpa>, by mjr@vax2.nlm.nih.gov.nlm.nih.gov (Marcus J. Ranum):
>> 	I wonder how much code would break is such an extension were added,
>> and the #include_once were made the DEFAULT rather than the exception ? 
>
> Ok, people! Would this change, made silently, injure correct
>programs?  It is admitted that it may allow incorrect programs to
>compile, but that isn't waht I'm concerned about.

Most certainly.  There is a programming method used by the GNU C compiler
and other programs which is to create a file of definitions (expressed
as macro invocations) which gets included more than once.  For
example, in GCC the file tree.def contains lines like:

	DEFTREECODE (ERROR_MARK, "error_mark", "x", 0)
	DEFTREECODE (IDENTIFIER_NODE, "identifier_node", "x", 6)
	DEFTREECODE (TREE_LIST, "tree_list", "x", 2)

One then defines the macro DEFTREECODE to do whatever one wants and
then #include's tree.def.  For example, in tree.c:

	#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,

	char *tree_code_type[] = {
	#include "tree.def"
	};
	#undef DEFTREECODE

	#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,

	int tree_code_length[] = {
	#include "tree.def"
	};
	#undef DEFTREECODE

I also have a header file that generates a function to do a bitblt for
a given binary operation.  One #define's a macro to specify the binary
operation and then #include's the file.  This is usually repeated for
each of the binary operations.

-- 
_.John G. Myers		Internet: John.Myers@cs.cmu.edu
			LoseNet:  ...!seismo!inhp4!wiscvm.wisc.edu!give!up
"The world is full of bozos.  Some of them even have PhD's in Computer Science"
--