Subject: Re: problems with arpa/inet.h
To: None <current-users@NetBSD.ORG>
From: Greg A. Woods <woods@most.weird.com>
List: current-users
Date: 06/16/1998 12:23:59
[ On Sun, June 14, 1998 at 23:10:11 (-0400), der Mouse wrote: ]
> Subject: Re: problems with arpa/inet.h
>
> Wanna bet?
> 
> On NetBSD, mostly-current, <stdio.h> ends up including <sys/types.h>,
> <machine/types.h>, <sys/cdefs.h>, <machine/cdefs.h>, <machine/ansi.h>,
> <machine/endian.h>, and <sys/featuretest.h>.
> 
> Without nested inclusion, that means that I would have to explicitly
> include those eight files, in some to-be-determined order, in order to
> use stdio under your scheme.  (Or else that the contents of most of
> them would have to be imported into stdio.h, which at *best* would be a
> maintenance nightmare.)

Let's assume that the mess necessary to get one set of portable headers
is totally hidden (preprocessing would be one way to do this in real
life, though I like Jonathan's suggestion of defining where nesting is
appropriate, and where it's not, and not documenting the nesting used to
hide machine independence).  This would instantly reduce the list to
just:

	#include <sys/cdefs.h>
	#include <sys/types.h>
	#include <stdio.h>

Of course if it weren't for the prototypes using non-native types,
<stdio.h> would be all you would need.  Period.  ;-)

(Prototypes could be reduced to native-only types by partial
pre-processing too, though that would obviously rule out
cross-compilation possibilities unless variants were created for all
possible targets and the appropriate directory were selected
automatically by cc.  It might even speed compiling up!)

> > One of the very real problems with the trend towards nested includes
> > is that it leaves novices out in the cold when it comes to
> > understanding what's truely necessary to define and/or use an
> > interface.
> 
> Novices have no business defining system interfaces; for their own, of
> course, it's a design decision which route to take.

Sorry, I meant "defining" in the C sense.

> As for using the interface, which is easier?  To use?  To read?  To
> understand?  Which is harder for a novice programmer to fsck up?

It depends.  If you're trying to teach that novice to write portable
code (as opposed to writing code and then porting it), the latter is far
more appropriate.

> #include <db.h>
> 
> --vs--
> 
> /* Order may be wrong - list obtained from cc -M, order guessed at. */
> #include <machine/ansi.h>
> #include <machine/cdefs.h>
> #include <sys/cdefs.h>
> #include <sys/syslimits.h>
> #include <machine/limits.h>
> #include <machine/types.h>
> #include <sys/types.h>
> #include <db.h>
> /* and that's just for one particular release of NetBSD! */

Again if it were not for the need for type definitions in prototype
arguments (which could be eliminated by pre-processing all the system
headers to reduce all types to their native C types), only the following
should be necessary:

	#include <sys/cdefs.h>
	#include <sys/types.h>
	#include <limits.h>
	#include <db.h>

In fact if you read the documented interface for db it shows almost
exactly what I've shown above, less <sys/cdefs.h>.  I've found that the
best way to write portable code is to provide a (portable) copy of
"sys/cdefs.h" with the package and use it where there is no
<sys/cdefs.h> available.  It makes things so much simpler.

> > Now instead of just reading the manual page programmers learning to
> > write portable code have to grub around deep in the guts of system
> > includes to try and discover what's truely necessary by unravelling
> > all the nested includes and learning all the true dependencies.
> 
> What on earth are you talking about?  The more you write, the more
> convinced I become that one of us has grossly misunderstood the other.

If you're going to write code that uses the original example from this
thread and expect it to compile unchanged on all systems that support
some variant of that interface then you cannot just write:

	#include <arpa/inet.h>

as The Single UNIX Specification (and any system manual pages that may
exist on a conforming system) might suggest.

You *must* instead write the originally specified:

	#include <sys/types.h>
	#include <sys/socket.h>
	#include <netinet/in.h>
	#include <arpa/inet.h>

> As I understand it, what you are attempting to argue against is the
> idea that an include file - <stdio.h>, <arpa/inet.h>, <fcntl.h>,
> whatever - should itself #include anything else necessary in order for
> it to function correctly.  That's certainly the idea I'm trying to
> argue for.

To a certain extent, yes.  I don't mind hiding the use of nested
includes to help build a set of machine independent headers as NetBSD
has done, but I sure as heck don't like the idea of over-simplifying
things to their ultimate end as The Single UNIX Specification has done.
It simply will not work in the real world -- code must still be written
to run on legacy non-conforming systems.

> > As much as I hate to plug "commercial" standards, "The Single UNIX
> > Specification" does an excellent job of defining exactly what headers
> > include which others,
> 
> Now I'm *sure* one of us is misunderstanding the other.  Not even a
> standards body would be crazy enough to try to specify the internals of
> how include files pull in other - internal - include files.
> 
> I hope.

Where it matters, they have done so (and must in order to ensure future
conforming implementations provide a predictable compilation environment).
 
> > If you're going to actually try and fix all these "problems" [...],
> > I'd recommend at least browsing the online version of that
> > specification to see if you can be compatible with it.
> 
> I might even do so, if I had a pointer to it.

Start here:

	http://www.rdg.opengroup.org/

or here:

	http://www.UNIX-systems.org/online.html
 
-- 
							Greg A. Woods

+1 416 443-1734      VE3TCP      <gwoods@acm.org>      <robohack!woods>
Planix, Inc. <woods@planix.com>; Secrets of the Weird <woods@weird.com>