The Unix Heritage Society mailing list
 help / color / mirror / Atom feed
* [TUHS] Mac OS X is Unix
@ 2017-01-03 20:19 Doug McIlroy
  2017-01-03 21:05 ` Charles Anthony
                   ` (4 more replies)
  0 siblings, 5 replies; 20+ messages in thread
From: Doug McIlroy @ 2017-01-03 20:19 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1213 bytes --]

> keeping the code I work on portable between Linux and the Mac requires
> more than a bit of ‘ifdef’ hell.

Curmudgeonly comment: I bristle at the coupling of "ifdef" and "portable".
Ifdefs that adjust code for different systems are prima facie
evidence of NON-portability. I'll buy "configurable" as a descriptor
for such ifdef'ed code, but not "portable".

And, while I am venting about ifdef:
As a matter of sytle, ifdefs are global constructs. Yet they often
have local effects like an if statement. Why do we almost always write

#ifdef LINUX
	linux code
#else
	default unix code
#endif

instead of the much cleaner

	if(LINUX)
		linux code
	else
		default unix code

In early days the latter would have cluttered precious memory
with unfreachable code, but now we have optimizing compilers
that will excise the useless branch just as effectively as cpp.

Much as the trait of overeating has been ascribed to our
hunter ancestors' need to eat fully when nature provided,
so overuse of ifdef echos coding practices tuned to
the capabilities of bygone computing systems.

"Ifdef hell" is a fitting image for what has to be one of
Unix's least felicitous contributions to computing. Down
with ifdef!
Doug


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

* [TUHS] Mac OS X is Unix
  2017-01-03 20:19 [TUHS] Mac OS X is Unix Doug McIlroy
@ 2017-01-03 21:05 ` Charles Anthony
  2017-01-03 21:33   ` [TUHS] When was #if introduced in C? (was: Re: Mac OS X is Unix) Michael Kjörling
  2017-01-03 21:35 ` [TUHS] Mac OS X is Unix Clem Cole
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 20+ messages in thread
From: Charles Anthony @ 2017-01-03 21:05 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2168 bytes --]

On Tue, Jan 3, 2017 at 12:19 PM, Doug McIlroy <doug at cs.dartmouth.edu> wrote:

> > keeping the code I work on portable between Linux and the Mac requires
> > more than a bit of ‘ifdef’ hell.
>
> Curmudgeonly comment: I bristle at the coupling of "ifdef" and "portable".
> Ifdefs that adjust code for different systems are prima facie
> evidence of NON-portability. I'll buy "configurable" as a descriptor
> for such ifdef'ed code, but not "portable".
>
> And, while I am venting about ifdef:
> As a matter of sytle, ifdefs are global constructs. Yet they often
> have local effects like an if statement. Why do we almost always write
>
> #ifdef LINUX
>         linux code
> #else
>         default unix code
> #endif
>
> instead of the much cleaner
>
>         if(LINUX)
>                 linux code
>         else
>                 default unix code
>
> In early days the latter would have cluttered precious memory
> with unfreachable code, but now we have optimizing compilers
> that will excise the useless branch just as effectively as cpp.
>
>
I have seen an interesting failure for the latter construct; I was
compiling some [unremembered] chess program for some [unremembered] UNIX
workstation in the late '80s.

The code had bit array data structures with get/set routines that optimized
for host word size, with code something like:

    if (sizeof (unsigned int) == 64)
        {
           // cast structure into array of 64 bit unsigned ints and use bit
operators
        }
    else  // sizeof (int) == 32
        {
           // cast structure into array of 32 bit unsigned ints and use bit
operators
        }

(It might of been 32/16; I don't remember, but it isn't relevant)

The '64' branch had an expression containing something like  '1u << 60' in
it.

I was compiling on a 32 bit int machine; the compiler flagged the '1u <<
60' as a fatal error due to the size of the shift -- on this compiler the
expression evaluator was running before the dead code remover.

-- Charles
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://minnie.tuhs.org/pipermail/tuhs/attachments/20170103/00cbfab3/attachment.html>


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

* [TUHS] When was #if introduced in C? (was: Re: Mac OS X is Unix)
  2017-01-03 21:05 ` Charles Anthony
@ 2017-01-03 21:33   ` Michael Kjörling
  2017-01-03 21:53     ` Robert Swierczek
  2017-01-03 21:56     ` Clem Cole
  0 siblings, 2 replies; 20+ messages in thread
From: Michael Kjörling @ 2017-01-03 21:33 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1267 bytes --]

On 3 Jan 2017 13:05 -0800, from charles.unix.pro at gmail.com (Charles Anthony):
> I was compiling on a 32 bit int machine; the compiler flagged the '1u <<
> 60' as a fatal error due to the size of the shift -- on this compiler the
> expression evaluator was running before the dead code remover.

That was my thought too; the only way to guarantee that the code is
removed before the compiler sees it is to do so through the
preprocessor, thus #ifdef.

Of course, #ifdef is rather limited. The #if preprocessor directive is
more generic, but still significantly less versatile than the if()
language keyword.

Which makes me curious... Does anyone here happen to know when #if was
introduced in C? I suspect #ifdef came earlier simply by virtue of
being (at least to a naiive first approximation) far easier to
implement, as all that would be required would be to look at the macro
expansion table (already required by #define) and see if that
particular name had previously been #defined, as opposed to actually
evaluating an expression.

-- 
Michael Kjörling • https://michael.kjorling.se • michael at kjorling.se
                 “People who think they know everything really annoy
                 those of us who know we don’t.” (Bjarne Stroustrup)


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

* [TUHS] Mac OS X is Unix
  2017-01-03 20:19 [TUHS] Mac OS X is Unix Doug McIlroy
  2017-01-03 21:05 ` Charles Anthony
@ 2017-01-03 21:35 ` Clem Cole
  2017-01-03 22:10   ` Lyndon Nerenberg
  2017-01-03 21:39 ` Lyndon Nerenberg
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 20+ messages in thread
From: Clem Cole @ 2017-01-03 21:35 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2555 bytes --]

On Tue, Jan 3, 2017 at 3:19 PM, Doug McIlroy <doug at cs.dartmouth.edu> wrote:

> Curmudgeonly comment: I bristle at the coupling of "ifdef" and "portable".
> Ifdefs that adjust code for different systems are prima facie
> evidence of NON-portability. I'll buy "configurable" as a descriptor
> for such ifdef'ed code, but not "portable".
>

​I hear you and partially agree.  But I would point out that my experience
in 40+ years of professional "coding" the programs that have "lasted" the
longest and matured the most over time, were all written in a language that
had some sort of preprocessor.​  Using a preprocessor is not a bad thing,
it's the miss use that is the problem and leaving it out I think weakens
the language.

IIRC: Brian made this same point in the "Why Pascal is not my Favorite
Programming Language."

I think your point of over use, is valid (like symlinks in the file system
- my curmudgeonly beef) - just because we >>have<< a feature does not make
it the best way to do something.   I like to think of this sort of choice
as "good taste" --  simple and elegant.    ifdef's are a real solution to a
problem.   But like you, I >>hate<< seeing them all over the place and they
certainly can muck up the code.

BTW:  I much prefer a local_func.c which sucks in unix_bindings.c,
vms_bindings.c, winders_bindings.c or the like with ifdefs and alls the
configuration control needed in >>one<< place;  and then all of the rest of
the code try to be a pure as possible as you describe.

FWIW: One of the best I ever saw was the old FORTRAN SPICE 2G6 of Ellis
Cohen and Tom Quarles.   That program runs everywhere (still does).   Ellis
and Tom used m4 to preprocess it, IIRC and keeps the localization in a very
controlled space.   If you even looked at it, Ellis does some really
imaginative coding (compiling the internal loop in a data block and jump to
it), it all portable and actually very easy to understand.  For one thing
the comments are there and very, clear.

But Ellis has great style and have mopped up after a number of other of the
UCB greats in those days, I'd much rather deal with Ellis's and TQ's code
base then some of my other peeps.

Anyway - I agree - ifdef >>is<< miss used in way too much code, but I think
part of that is so many programmers never had a real software engineering
course ( a thought I will follow up in another thread).

Clem
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://minnie.tuhs.org/pipermail/tuhs/attachments/20170103/90d1f5af/attachment.html>


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

* [TUHS] Mac OS X is Unix
  2017-01-03 20:19 [TUHS] Mac OS X is Unix Doug McIlroy
  2017-01-03 21:05 ` Charles Anthony
  2017-01-03 21:35 ` [TUHS] Mac OS X is Unix Clem Cole
@ 2017-01-03 21:39 ` Lyndon Nerenberg
  2017-01-03 22:12   ` ron minnich
  2017-01-04  0:13 ` Steve Johnson
  2017-01-04  3:50 ` Dan Cross
  4 siblings, 1 reply; 20+ messages in thread
From: Lyndon Nerenberg @ 2017-01-03 21:39 UTC (permalink / raw)


> #ifdef LINUX
> 	linux code
> #else
> 	default unix code
> #endif
> 
> instead of the much cleaner
> 
> 	if(LINUX)
> 		linux code
> 	else
> 		default unix code
> 
> In early days the latter would have cluttered precious memory
> with unfreachable code, but now we have optimizing compilers
> that will excise the useless branch just as effectively as cpp.

Plan 9 refreshingly evicted this nonsense from the native compilers (mostly) and the code base.[1]

I remember reading a Usenet post from the mid-late 80s that showed a roughly 40 line sequence of #foo hell from some bit of SVRx code.  There wasn't a single line of actual C there.  That it involved conditionalizing around the tty/termio drivers and some machine-specific ioctl goop ... well, let's not go *there*.

It might have been posted as an example for the Obfuscated C Contest.  It certainly could have won. (Assuming an entry without any actual C code was eligible.  Vague memories say anything that survived 'cc -o foo xxx.c [...]' was allowed.)

--lyndon

[1] Eliminating many binary APIs -- e.g. ioctl() -- in favour of textual ones, was a stroke of genius.  Not just with fileservers (/net et al), but also with things like dial().


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

* [TUHS] When was #if introduced in C? (was: Re: Mac OS X is Unix)
  2017-01-03 21:33   ` [TUHS] When was #if introduced in C? (was: Re: Mac OS X is Unix) Michael Kjörling
@ 2017-01-03 21:53     ` Robert Swierczek
  2017-01-03 21:57       ` Clem Cole
  2017-01-03 21:56     ` Clem Cole
  1 sibling, 1 reply; 20+ messages in thread
From: Robert Swierczek @ 2017-01-03 21:53 UTC (permalink / raw)


> Which makes me curious... Does anyone here happen to know when #if was introduced in C?

From what I can gather from studying the TUHS archives, the earliest
cpp that supports #if is in PWB:
http://minnie.tuhs.org/cgi-bin/utree.pl?file=PWB1/sys/c/c/cpp.c

Before that, the pre-processor resides within the cc.c command and #if
is not supported:
http://minnie.tuhs.org/cgi-bin/utree.pl?file=V6/usr/source/s1/cc.c


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

* [TUHS] When was #if introduced in C? (was: Re: Mac OS X is Unix)
  2017-01-03 21:33   ` [TUHS] When was #if introduced in C? (was: Re: Mac OS X is Unix) Michael Kjörling
  2017-01-03 21:53     ` Robert Swierczek
@ 2017-01-03 21:56     ` Clem Cole
  1 sibling, 0 replies; 20+ messages in thread
From: Clem Cole @ 2017-01-03 21:56 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2069 bytes --]

The cpp.c code in 6th edition only supported #ifdef.   IIRC the v7 cpp had
#if, but it may have been in typesetter C.   I think mashey needed it for
SCCS (I don't have sources easy to look at PWB 1.0), so my guess is it was
developed during that transition.  The key is that  PWB 1.0 was a v6++
system.   UNIX/TS and later V7 had the newer kernel.   PWB 2.0 was based on
that one.    The typesetter compiler was developed in parallel to those
projects, which also put constraints on the language.

Clem

On Tue, Jan 3, 2017 at 4:33 PM, Michael Kjörling <michael at kjorling.se>
wrote:

> On 3 Jan 2017 13:05 -0800, from charles.unix.pro at gmail.com (Charles
> Anthony):
> > I was compiling on a 32 bit int machine; the compiler flagged the '1u <<
> > 60' as a fatal error due to the size of the shift -- on this compiler the
> > expression evaluator was running before the dead code remover.
>
> That was my thought too; the only way to guarantee that the code is
> removed before the compiler sees it is to do so through the
> preprocessor, thus #ifdef.
>
> Of course, #ifdef is rather limited. The #if preprocessor directive is
> more generic, but still significantly less versatile than the if()
> language keyword.
>
> Which makes me curious... Does anyone here happen to know when #if was
> introduced in C? I suspect #ifdef came earlier simply by virtue of
> being (at least to a naiive first approximation) far easier to
> implement, as all that would be required would be to look at the macro
> expansion table (already required by #define) and see if that
> particular name had previously been #defined, as opposed to actually
> evaluating an expression.
>
> --
> Michael Kjörling • https://michael.kjorling.se • michael at kjorling.se
>                  “People who think they know everything really annoy
>                  those of us who know we don’t.” (Bjarne Stroustrup)
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://minnie.tuhs.org/pipermail/tuhs/attachments/20170103/0feb52a9/attachment.html>


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

* [TUHS] When was #if introduced in C? (was: Re: Mac OS X is Unix)
  2017-01-03 21:53     ` Robert Swierczek
@ 2017-01-03 21:57       ` Clem Cole
  0 siblings, 0 replies; 20+ messages in thread
From: Clem Cole @ 2017-01-03 21:57 UTC (permalink / raw)


Great minds think alike..   This lines up with my memory.

On Tue, Jan 3, 2017 at 4:53 PM, Robert Swierczek <rmswierczek at gmail.com>
wrote:

> > Which makes me curious... Does anyone here happen to know when #if was
> introduced in C?
>
> From what I can gather from studying the TUHS archives, the earliest
> cpp that supports #if is in PWB:
> http://minnie.tuhs.org/cgi-bin/utree.pl?file=PWB1/sys/c/c/cpp.c
>
> Before that, the pre-processor resides within the cc.c command and #if
> is not supported:
> http://minnie.tuhs.org/cgi-bin/utree.pl?file=V6/usr/source/s1/cc.c
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://minnie.tuhs.org/pipermail/tuhs/attachments/20170103/58878a3a/attachment.html>


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

* [TUHS] Mac OS X is Unix
  2017-01-03 21:35 ` [TUHS] Mac OS X is Unix Clem Cole
@ 2017-01-03 22:10   ` Lyndon Nerenberg
  0 siblings, 0 replies; 20+ messages in thread
From: Lyndon Nerenberg @ 2017-01-03 22:10 UTC (permalink / raw)



> On Jan 3, 2017, at 1:35 PM, Clem Cole <clemc at ccc.com> wrote:
> 
> If you even looked at it, Ellis does some really imaginative coding (compiling the internal loop in a data block and jump to it), it all portable and actually very easy to understand.  For one thing the comments are there and very, clear.

But that's not going to survive modern W^X.  Unless you compile to interpreted byte-code, which mostly wipes out the inline loop unroll to machine code, no?


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

* [TUHS] Mac OS X is Unix
  2017-01-03 21:39 ` Lyndon Nerenberg
@ 2017-01-03 22:12   ` ron minnich
  2017-01-03 23:39     ` Tim Bradshaw
  0 siblings, 1 reply; 20+ messages in thread
From: ron minnich @ 2017-01-03 22:12 UTC (permalink / raw)


On Tue, Jan 3, 2017 at 2:07 PM Lyndon Nerenberg <lyndon at orthanc.ca> wrote:

>
>
> Plan 9 refreshingly evicted this nonsense from the native compilers
> (mostly) and the code base.[1]
>

Yes, You can write portable code without #ifdef, configure scripts, and
libtool. Plan 9 shows how.

Some people get upset at mentions of Plan 9, however, so for a more current
example, the Go source tree is a good reference. There's no cpp in Go,
thank goodness, and they've shown superior portability to systems that
revolve around #ifdef.

ron
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://minnie.tuhs.org/pipermail/tuhs/attachments/20170103/91f6f07e/attachment-0001.html>


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

* [TUHS] Mac OS X is Unix
  2017-01-03 22:12   ` ron minnich
@ 2017-01-03 23:39     ` Tim Bradshaw
  2017-01-04  0:12       ` ron minnich
  0 siblings, 1 reply; 20+ messages in thread
From: Tim Bradshaw @ 2017-01-03 23:39 UTC (permalink / raw)


I think you can do so only if every language processor you ever expect to deal with your code is lexically-compatible: you *can't* do so if the lexer will puke: you need some frontend which will prevent the lexer ever seeing the toxin, and that thing is what Lisp would call read-time conditionalization.  Plan 9 and Go both avoid this problem by being single-implementation or nearly-single-implementation systems: many things are easier with that assumption.

> On 3 Jan 2017, at 22:12, ron minnich <rminnich at gmail.com> wrote:
> 
> 
> 
>> On Tue, Jan 3, 2017 at 2:07 PM Lyndon Nerenberg <lyndon at orthanc.ca> wrote:
>> 
>> 
>> Plan 9 refreshingly evicted this nonsense from the native compilers (mostly) and the code base.[1]
> 
> Yes, You can write portable code without #ifdef, configure scripts, and libtool. Plan 9 shows how.
> 
> Some people get upset at mentions of Plan 9, however, so for a more current example, the Go source tree is a good reference. There's no cpp in Go, thank goodness, and they've shown superior portability to systems that revolve around #ifdef.
> 
> ron
> 
>  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://minnie.tuhs.org/pipermail/tuhs/attachments/20170103/906d460f/attachment.html>


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

* [TUHS] Mac OS X is Unix
  2017-01-03 23:39     ` Tim Bradshaw
@ 2017-01-04  0:12       ` ron minnich
  2017-01-04  9:11         ` Tim Bradshaw
  0 siblings, 1 reply; 20+ messages in thread
From: ron minnich @ 2017-01-04  0:12 UTC (permalink / raw)


On Tue, Jan 3, 2017 at 3:39 PM Tim Bradshaw <tfb at tfeb.org> wrote:

> I think you can do so only if every language processor you ever expect to
> deal with your code is lexically-compatible: you *can't* do so if the lexer
> will puke: you need some frontend which will prevent the lexer ever seeing
> the toxin, and that thing is what Lisp would call read-time
> conditionalization.  Plan 9 and Go both avoid this problem by being
> single-implementation or nearly-single-implementation systems: many things
> are easier with that assumption.
>
>
>
Well, if by single-implementation, you mean single-compiler, I have a
counter example: Harvey is Plan 9 with just enough changed to be C11
compliant. All of userland, libraries, and kernel build and boot with gcc
4, 5,6 and clang 3.5, 3.6, and 3.8. Harvey builds and boots on amd64 and
riscv. We've adhered as much as we can to the coding style of Plan 9 and
we've seen the benefits. Probably the only major change was removal of
anonymous struct members, and that actually improved the code as it
uncovered some long-standing driver bugs.

In contrast, it's very hard to build portable code that uses extensive
ifdefs and 'modern' tools like libtool today. Just the other day I had a
 build failure because something needed autotools x.6.61 and I only had
x.y.60. Portable seems to now mean 'builds on ubuntu AND Fedora!' and even
that's rare.

The portability principles used in Plan 9 work just fine with 'modern'
compilers. The cpp abuse we see in so much code today seems completely
unnecessary to me. C code written with #ifdefs and libtool is far less
portable than it might be.

ron
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://minnie.tuhs.org/pipermail/tuhs/attachments/20170104/8eb183c4/attachment.html>


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

* [TUHS] Mac OS X is Unix
  2017-01-03 20:19 [TUHS] Mac OS X is Unix Doug McIlroy
                   ` (2 preceding siblings ...)
  2017-01-03 21:39 ` Lyndon Nerenberg
@ 2017-01-04  0:13 ` Steve Johnson
  2017-01-04  3:50 ` Dan Cross
  4 siblings, 0 replies; 20+ messages in thread
From: Steve Johnson @ 2017-01-04  0:13 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2866 bytes --]

Following on Doug's comment, when I wrote the portable C compiler my
vision was to separate out the machine independent parts of the
compiler (e.g, the lexer and parser) from the machine dependent parts
(those parts involving stack frames, instructions, etc.).  Then to
port the compiler, you could leave the machine independent code alone
(much of which was rather hairy, involving symbol tables,
optimizations, etc.) and simply describe the instructions and calling
sequence in the machine dependent files.  The preprocessor was
actually pretty important in carrying this out, because there were a
fair number of machine characteristics ( such as byte order and word
size) that were handled identically across different architectures but
the actual values were different.  These were handled by defining
some preprocessor macros.

Several years later, I had moved to development and was responsible
for shipping a variety of different compilers, most resting on the PCC
base.  At one point, I was appalled to see that somebody had put some
code into one of the machine-independent files that was bracketed with
"# ifdef VAX".  There followed a most difficult conversation with the
perpetrator who kept insisting that, after all, the code WAS the same
on all machines...

----- Original Message -----
From: "Doug McIlroy" <doug@cs.dartmouth.edu>
To:<tuhs at minnie.tuhs.org>
Cc:
Sent:Tue, 03 Jan 2017 15:19:08 -0500
Subject:Re: [TUHS] Mac OS X is Unix

 > keeping the code I work on portable between Linux and the Mac
requires
 > more than a bit of ‘ifdef’ hell.

 Curmudgeonly comment: I bristle at the coupling of "ifdef" and
"portable".
 Ifdefs that adjust code for different systems are prima facie
 evidence of NON-portability. I'll buy "configurable" as a descriptor
 for such ifdef'ed code, but not "portable".

 And, while I am venting about ifdef:
 As a matter of sytle, ifdefs are global constructs. Yet they often
 have local effects like an if statement. Why do we almost always
write

 #ifdef LINUX
 linux code
 #else
 default unix code
 #endif

 instead of the much cleaner

 if(LINUX)
 linux code
 else
 default unix code

 In early days the latter would have cluttered precious memory
 with unfreachable code, but now we have optimizing compilers
 that will excise the useless branch just as effectively as cpp.

 Much as the trait of overeating has been ascribed to our
 hunter ancestors' need to eat fully when nature provided,
 so overuse of ifdef echos coding practices tuned to
 the capabilities of bygone computing systems.

 "Ifdef hell" is a fitting image for what has to be one of
 Unix's least felicitous contributions to computing. Down
 with ifdef!
 Doug

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://minnie.tuhs.org/pipermail/tuhs/attachments/20170103/4a996b9d/attachment-0001.html>


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

* [TUHS] Mac OS X is Unix
  2017-01-03 20:19 [TUHS] Mac OS X is Unix Doug McIlroy
                   ` (3 preceding siblings ...)
  2017-01-04  0:13 ` Steve Johnson
@ 2017-01-04  3:50 ` Dan Cross
  2017-01-04 12:26   ` Tim Bradshaw
  4 siblings, 1 reply; 20+ messages in thread
From: Dan Cross @ 2017-01-04  3:50 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 3688 bytes --]

On Tue, Jan 3, 2017 at 3:19 PM, Doug McIlroy <doug at cs.dartmouth.edu> wrote:

> > keeping the code I work on portable between Linux and the Mac requires
> > more than a bit of ‘ifdef’ hell.
>
> Curmudgeonly comment: I bristle at the coupling of "ifdef" and "portable".
> Ifdefs that adjust code for different systems are prima facie
> evidence of NON-portability. I'll buy "configurable" as a descriptor
> for such ifdef'ed code, but not "portable".
>

Here, here.

And, while I am venting about ifdef:
> As a matter of sytle, ifdefs are global constructs. Yet they often
> have local effects like an if statement. Why do we almost always write
>
> #ifdef LINUX
>         linux code
> #else
>         default unix code
> #endif
>
> instead of the much cleaner
>
>         if(LINUX)
>                 linux code
>         else
>                 default unix code
>
> In early days the latter would have cluttered precious memory
> with unfreachable code, but now we have optimizing compilers
> that will excise the useless branch just as effectively as cpp.
>

Interesting, but I'm curious how this would work in the context of C (or a
C-like variant)? The code must parse and type-check in accordance with the
existing standard, no? So if the `if(LINUX)` branch referred to, say,
Linux-specific structure members, then how would the compiler recognize
that avoid spitting out a diagnostic/erroring out? The existing C language
seems defined to expressly disallow this sort of thing.

What might be interesting would be an additional lexical token that would
tag a particular expression as, "compile-time evaluated" with the
consequence that the compiler would ignore the following statement or block
if it appeared in a conditional (or something along those lines). It would
be an error if such a conditional did not evaluate to a compile-time
constant. So one might say something along the lines of, `if #(LINUX) { ...
}` (or whatever syntax was reasonable and allowable with respect to the
existing language) and this would be ignored by the compiler on systems for
which LINUX evaluated to logical false (0 or whatever the kids call it
these days). I imagine this would open other cans of worms, though.

Much as the trait of overeating has been ascribed to our
> hunter ancestors' need to eat fully when nature provided,
> so overuse of ifdef echos coding practices tuned to
> the capabilities of bygone computing systems.
>
> "Ifdef hell" is a fitting image for what has to be one of
> Unix's least felicitous contributions to computing. Down
> with ifdef!
>

I've learned two hard lessons about #ifdef.

First, one should strive to avoid them by programming to an abstract
interface, with "system" specific implementations of that interface that
are selected by the build system (make, mk, whatever). I've further found
that one rarely needs complicated shell scripts for things like that.

Second, if one cannot avoid them, one should #ifdef around a particular
feature, not a system. For example, instead of `#if defined(__linux__) ||
defined(__FreeBSD__) || defined(__OpenBSD__) || ... // Use mmap()` all over
the place, one should just, `#ifdef PROJECT_USE_MMAP` and `#define
PROJECT_USE_MMAP` for one's project somewhere (possibly based on system
there or whatever). Then adding a new system is relatively easier: one
defines a set of symbols for the new system, instead of trying to find
every place where __linux__ is tested and adding to that.

Ideally, one would avoid #if, though.

        - Dan C.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://minnie.tuhs.org/pipermail/tuhs/attachments/20170103/4dd38998/attachment.html>


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

* [TUHS] Mac OS X is Unix
  2017-01-04  0:12       ` ron minnich
@ 2017-01-04  9:11         ` Tim Bradshaw
  2017-01-04 10:04           ` Álvaro Jurado
  0 siblings, 1 reply; 20+ messages in thread
From: Tim Bradshaw @ 2017-01-04  9:11 UTC (permalink / raw)


So, can you build the system with both  C11 compiler and its older compiler, from the same sources (so, no keeping two copies of the same functionality and selecting at build time based on the compiler)?  If you can I'm impressed.

> On 4 Jan 2017, at 00:12, ron minnich <rminnich at gmail.com> wrote:
> 
> Well, if by single-implementation, you mean single-compiler, I have a counter example: Harvey is Plan 9 with just enough changed to be C11 compliant.



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

* [TUHS] Mac OS X is Unix
  2017-01-04  9:11         ` Tim Bradshaw
@ 2017-01-04 10:04           ` Álvaro Jurado
  0 siblings, 0 replies; 20+ messages in thread
From: Álvaro Jurado @ 2017-01-04 10:04 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1507 bytes --]

Not. Plan 9 developed a significant dependency of its original compilers.
Plan 9 cc is a caller compiler so main parts of the code couldn't work now
adapted in Harvey for gcc, clang and icc (intel) that are all callee. But
it's not a C problem, it's a compiler issue. Probably with Steve's pcc you
could too. Nerver tried, but it could be a good experiment.
At the end is extremely difficult not to be at any point toolchain
dependent, if Plan 9 original compilers could be improved enough to build
an standard ANSI program out of the tree (they are strongly dependent of
Plan 9 environment), also the Plan 9 code, that way you're suggesting would
be possible.
Anyway, for that, you wouldn't need any preprocessor code, also you
needen't to build amd64 or riscv with the same sources.

Álvaro

El 04/01/2017 10:12, "Tim Bradshaw" <tfb at tfeb.org> escribió:

> So, can you build the system with both  C11 compiler and its older
> compiler, from the same sources (so, no keeping two copies of the same
> functionality and selecting at build time based on the compiler)?  If you
> can I'm impressed.
>
> > On 4 Jan 2017, at 00:12, ron minnich <rminnich at gmail.com> wrote:
> >
> > Well, if by single-implementation, you mean single-compiler, I have a
> counter example: Harvey is Plan 9 with just enough changed to be C11
> compliant.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://minnie.tuhs.org/pipermail/tuhs/attachments/20170104/46bea0ca/attachment.html>


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

* [TUHS] Mac OS X is Unix
  2017-01-04  3:50 ` Dan Cross
@ 2017-01-04 12:26   ` Tim Bradshaw
  2017-01-04 13:49     ` Random832
  2017-01-04 15:02     ` Dan Cross
  0 siblings, 2 replies; 20+ messages in thread
From: Tim Bradshaw @ 2017-01-04 12:26 UTC (permalink / raw)


On 4 Jan 2017, at 03:50, Dan Cross <crossd at gmail.com> wrote:
> 
> Interesting, but I'm curious how this would work in the context of C (or a C-like variant)? The code must parse and type-check in accordance with the existing standard, no? So if the `if(LINUX)` branch referred to, say, Linux-specific structure members, then how would the compiler recognize that avoid spitting out a diagnostic/erroring out? The existing C language seems defined to expressly disallow this sort of thing.


Common Lisp has a notion of 'suppressing the reader' which basically means that the reader (which in CL is the thing which turns a stream of characters into the data structure that is the source code of the language) will do just enough to consume a form, but not any more than that.  In particular it will ignore all sorts of things which would make it very unhappy if it looked too closely at them.  And there are then read-time conditionals which will cause the reader to suppress the following thing, or not.  It seems to me that, even without defining how things work in the very fine-grained way that CL does (where the data structure the reader produces is defined and you can program the reader itself), a C-like language could define what it means to 'suppress' a form, and support conditionals which did that.  I think, reading again, that this might be quite close to your compile-time-evaluated idea.

The thing to avoid is 'language in a string', where one language contains another language in strings (or equivalent), because then you end up putting the inner language together by concatenating strings, which can cross-cut constructs in the inner language in a horrible way.  C is the language in a string of the C preprocessor.  Where I work we use a tool which has a deeply horrible preprocessor which has the main syntax as its language in a string.  That syntax *in turn* has a whole other language in its strings.  Every time I look at this I want to hit someone.

--tim
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://minnie.tuhs.org/pipermail/tuhs/attachments/20170104/c241047f/attachment.html>


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

* [TUHS] Mac OS X is Unix
  2017-01-04 12:26   ` Tim Bradshaw
@ 2017-01-04 13:49     ` Random832
  2017-01-04 15:02     ` Dan Cross
  1 sibling, 0 replies; 20+ messages in thread
From: Random832 @ 2017-01-04 13:49 UTC (permalink / raw)


On Wed, Jan 4, 2017, at 07:26, Tim Bradshaw wrote:
> The thing to avoid is 'language in a string', where one language contains
> another language in strings (or equivalent), because then you end up
> putting the inner language together by concatenating strings, which can
> cross-cut constructs in the inner language in a horrible way.

What about having the *same* language in strings? Like TCL?


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

* [TUHS] Mac OS X is Unix
  2017-01-04 12:26   ` Tim Bradshaw
  2017-01-04 13:49     ` Random832
@ 2017-01-04 15:02     ` Dan Cross
  2017-01-04 17:14       ` tfb
  1 sibling, 1 reply; 20+ messages in thread
From: Dan Cross @ 2017-01-04 15:02 UTC (permalink / raw)


On Wed, Jan 4, 2017 at 7:26 AM, Tim Bradshaw <tfb at tfeb.org> wrote:

> On 4 Jan 2017, at 03:50, Dan Cross <crossd at gmail.com> wrote:
>
> Interesting, but I'm curious how this would work in the context of C (or a
> C-like variant)? The code must parse and type-check in accordance with the
> existing standard, no? So if the `if(LINUX)` branch referred to, say,
> Linux-specific structure members, then how would the compiler recognize
> that avoid spitting out a diagnostic/erroring out? The existing C language
> seems defined to expressly disallow this sort of thing.
>
> Common Lisp has a notion of 'suppressing the reader' which basically means
> that the reader (which in CL is the thing which turns a stream of
> characters into the data structure that is the source code of the language)
> will do just enough to consume a form, but not any more than that.  In
> particular it will ignore all sorts of things which would make it very
> unhappy if it looked too closely at them.  And there are then read-time
> conditionals which will cause the reader to suppress the following thing,
> or not.  It seems to me that, even without defining how things work in the
> very fine-grained way that CL does (where the data structure the reader
> produces is defined and you can program the reader itself), a C-like
> language could define what it means to 'suppress' a form, and support
> conditionals which did that.  I think, reading again, that this might be
> quite close to your compile-time-evaluated idea.
>

What I'm proposing is almost exactly like Common Lisp's `#-` and `#+`
(these use reader suppression, of course). Delving further into the realm
of reader macros and other Lisp-like reader things is, I think, a mistake:
the complexity of the reader is arguably a wart on the side of Common Lisp.

Of course, in C one doesn't have the notion of forms in the Lispy sense;
it's a statement based language. So the syntactical construct consumed by a
compile-time conditional would have to be specified to a greater level of
precision (e.g., an `if` selection-statement in C is followed by general
statement, in all of its richness). But the idea here is to create
something that works with the syntax of the language, not separate from it,
which is Lispy in character. A major problem of the preprocessor is that
it's sort of bolted onto the side of the language and doesn't work with it
very cleanly. On the other hand, it's kind of neat that one can use the
preprocessor for things that aren't C.

The thing to avoid is 'language in a string', where one language contains
> another language in strings (or equivalent), because then you end up
> putting the inner language together by concatenating strings, which can
> cross-cut constructs in the inner language in a horrible way.  C is the
> language in a string of the C preprocessor.  Where I work we use a tool
> which has a deeply horrible preprocessor which has the main syntax as its
> language in a string.  That syntax *in turn* has a whole other language in
> its strings.  Every time I look at this I want to hit someone.
>

Precisely why I wouldn't want reader macros in all of their hideous glory.
Consider LOOP. Ugh.

        - Dan C.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://minnie.tuhs.org/pipermail/tuhs/attachments/20170104/720d9f8d/attachment-0001.html>


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

* [TUHS] Mac OS X is Unix
  2017-01-04 15:02     ` Dan Cross
@ 2017-01-04 17:14       ` tfb
  0 siblings, 0 replies; 20+ messages in thread
From: tfb @ 2017-01-04 17:14 UTC (permalink / raw)


On 4 Jan 2017, at 15:02, Dan Cross <crossd at gmail.com> wrote:
> 
> What I'm proposing is almost exactly like Common Lisp's `#-` and `#+` (these use reader suppression, of course). Delving further into the realm of reader macros and other Lisp-like reader things is, I think, a mistake: the complexity of the reader is arguably a wart on the side of Common Lisp.


I kind of disagree about the CL reader in the context of CL, but strongly agree that such a thing would be a mistake for a C-family language.  but yes, #+ & #- are what I'd like for a C-family language.

As you say statement languages make this a bit harder: I've never understood why anyone thought they were a good idea (I think a C-level expression-language ought to be reasonably easy to do).
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://minnie.tuhs.org/pipermail/tuhs/attachments/20170104/fa7967af/attachment.html>


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

end of thread, other threads:[~2017-01-04 17:14 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-03 20:19 [TUHS] Mac OS X is Unix Doug McIlroy
2017-01-03 21:05 ` Charles Anthony
2017-01-03 21:33   ` [TUHS] When was #if introduced in C? (was: Re: Mac OS X is Unix) Michael Kjörling
2017-01-03 21:53     ` Robert Swierczek
2017-01-03 21:57       ` Clem Cole
2017-01-03 21:56     ` Clem Cole
2017-01-03 21:35 ` [TUHS] Mac OS X is Unix Clem Cole
2017-01-03 22:10   ` Lyndon Nerenberg
2017-01-03 21:39 ` Lyndon Nerenberg
2017-01-03 22:12   ` ron minnich
2017-01-03 23:39     ` Tim Bradshaw
2017-01-04  0:12       ` ron minnich
2017-01-04  9:11         ` Tim Bradshaw
2017-01-04 10:04           ` Álvaro Jurado
2017-01-04  0:13 ` Steve Johnson
2017-01-04  3:50 ` Dan Cross
2017-01-04 12:26   ` Tim Bradshaw
2017-01-04 13:49     ` Random832
2017-01-04 15:02     ` Dan Cross
2017-01-04 17:14       ` tfb

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).