[net.lang.c] ANSI C

mike@RICE.ARPA (07/05/84)

From:  Mike Caplinger <mike@RICE.ARPA>

I can't believe that somebody is proposing ANOTHER standard that imposes a
6-character uniqueness limit on external names!  How much longer are we
going to be stuck with somebody's 1960s linker implementation choice?

If ANSI got real and made the names of reasonable length, maybe that would
force some of these sleazy people to write a real linker!

	- Mike Caplinger

DBrown@HI-MULTICS.ARPA (07/05/84)

This message is empty.

gwyn@brl-tgr.UUCP (07/06/84)

More likely there will be ADAs with 6-character line length limits imposed.

henry@utzoo.UUCP (Henry Spencer) (07/08/84)

Mike Caplinger observes:

   I can't believe that somebody is proposing ANOTHER standard that imposes a
   6-character uniqueness limit on external names!  How much longer are we
   going to be stuck with somebody's 1960s linker implementation choice?
   
   If ANSI got real and made the names of reasonable length, maybe that would
   force some of these sleazy people to write a real linker!

The 6-character uniqueness limit is not being "imposed" by the standard;
it is already imposed by dozens of linkers in use at tens of thousands
of sites.  This is (a) most unfortunate, but (b) extremely hard to fix.
Many, many C users work on systems which are constrained to be backwards
compatible with "somebody's 1960s linker implementation choice" forever,
or very nearly so.  It is a fact, regrettable but unavoidable, that C
programs which need more than 6-characters-monocase to distinguish among
their external identifiers are not portable, period.  This is not going
to be changed by wishing it away.  The ANSI folks have chosen to recognize
this fact rather than ignore it.

There is a fundamental question of standards politics here:  should the
standard attempt to tidy up and codify existing stuff, or should it try
to change the world by inventing all kinds of new goodies?  The problem
with the latter approach is that it's hard to stop the standards group
once they've got the bit between their teeth, and the result is often
nearly unrecognizable.  WE DON'T WANT THIS TO HAPPEN TO C!!  Many people,
including me, breathed a sigh of relief when it became clear that the ANSI
C people were taking the conservative but safe path of deferring to reality
rather than defying it.

These things are always compromises.  People in an environment with fairly
controllable software will probably have either 31-character external names
(consistent with the internal names) or unlimited-length external names
fairly soon.  Folks in environments with uncontrollable software won't be
able to upgrade, and portability to such environments will remain an issue
that cannot be ignored.  This being the case, the ANSI C folks have chosen
to write their standard in such a way that it is compatible with most
existing environments, not just the fortunate few.
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry

dgary@ecsvax.UUCP (07/11/84)

<>
>From: henry@utzoo.UUCP (Henry Spencer) Sat Jul  7 20:11:41 1984
>The 6-character uniqueness limit is not being "imposed" by the standard;
>it is already imposed by dozens of linkers in use at tens of thousands
>of sites.

A minor point:  The linker imposes a limit only on the number of
significant characters in EXTERNAL names.  K&R claim internal names
can have 8 significant characters.  I see no reason for a limit on
external names to be imposed on the whole language.

D Gary Grady
Duke University Computation Center, Durham, NC  27706
(919) 684-4146
USENET:  {decvax,ihnp4,akgua,etc.}!mcnc!ecsvax!dgary

ron@brl-tgr.ARPA (Ron Natalie <ron>) (07/12/84)

Unfortunately a lot of C/UNIX implementations don't even get this right.
The trick of sticking an underscore in front of C symbols causes the
eight significant characters to become nine.  The assembler on the PDP-11's
only had eight significant characters in the symbol names.  Variables that
differed only in their eighth and later characters fell through the C
symbol checks and caused the assembler to blow up with funny "m" error
messages.

-Ron

henry@utzoo.UUCP (Henry Spencer) (07/15/84)

> A minor point:  The linker imposes a limit only on the number of
> significant characters in EXTERNAL names.  K&R claim internal names
> can have 8 significant characters.  I see no reason for a limit on
> external names to be imposed on the whole language.

Please read my original summary more closely.  The 6-character limit
applies only to external names.  The limit for internal names is much
easier to change, and the current draft standard has it as 31 rather
than merely 8.
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry

gwyn@BRL.ARPA (VLD/VMB) (11/22/85)

difftime() accepts time_t arguments but returns a double.
Its result is expressed in SECONDS, whereas a time_t is not
necessarily expressed in seconds.  There is no portable way
to do simple arithmetic on general time_t values to produce
a time difference in seconds, hence difftime().

gmtime(), like time(), ctime(), and localtime(), takes a
pointer to a time_t because that's what they already do.
These functions have been defined (in UNIX at least) for a
long time (no pun intended).

Really, guys, the X3J11 committee has been doing a very nice
job, much better than "obviously didn't put much thought into
anything related to times".  Seems to me they put more thought
into it than some of their detractors..

gwyn@BRL.ARPA (VLD/VMB) (11/23/85)

As an X3J11 C implementor, it would be your job to
arrange for the correct operation of routines such
as gmtime().  This CAN be done on any non-UNIX system.
2.nBSD (for n around 3) even implemented per-user
environments without kernel support.

For example (not necessarily optimum), DST could be
indicated by the presence of a specific system file.
The implementation of gmtime() would test for this
(the first time it is called within the process).

I think the concept of DST is stupid, but so long as
it has to be dealt with, some means must be provided.

Makey@logicon.arpa (Jeff Makey) (11/23/85)

The daylight time flag returned by localtime() does NOT have to be
provided by the operating system.  I looked at the 10-year-old source
code on my PDP-11/70 PWB UNIX system (no environment variables) and
observed that localtime() *computes* whether or not the date it is
processing is between the last Sundays in April and October.  The ONLY
input to localtime() (it makes no system calls) is a GMT date/time
value that is immediately converted to local standard time, then to
daylight time if appropriate.  There are static variables that are
hard-coded to indicate: the difference in hours between GMT and local
standard time; and whether or not conversion to daylight time should
ever occur (useful throughout most of Indiana, where they are always on
eastern standard time).

                            :: Jeff Makey
                               Makey@LOGICON.ARPA

peter@graffiti.UUCP (Peter da Silva) (11/24/85)

> I think the concept of DST is stupid, but so long as
> it has to be dealt with, some means must be provided.

Perhaps, perhaps, but it'd be better to leave that up to the application
instead of stuffing the library or forcing some PC user to create a file
at certain times of the year just to run some program that happens to be
written in 'C'. In addition, the X3J11 draft I read explicitly stated time_t
was a number of seconds, not a magic cookie that had to be difftime()-ed
if one wanted to do comparisons. Even if it is, on other systems floating
point support is relatively expensive in terms of memory, which would make
difftime() an unnaceptable burden on the implementor.

The basic complaint is that X3J11 is not a description of 'C', but rather a
description of 'C' under UNIX. There is a good deal of stuff in it that
should not be in the language definition, but rather in a standard
extension: the UNIX compatibility package, for example. I like UNIX, and
I'd like nothing better than to see it become the standard O/S for non
real-time applications (how does one deal with the DST in some little
standalone 'C' program in an RTU in Oman somewhere? They don't even use
it...), but I don't expect it to happen. I like 'C', and I sure hope that
it doesn't become restricted to UNIX and UNIX-like systems.

That's what I see happening, however, unless X3J11 is (a) ignored or (b)
fixed. And I hope that if they don't (b) fix it, everyone else follows my
example and (a) ignores it.
-- 
Name: Peter da Silva
Graphic: `-_-'
UUCP: ...!shell!{graffiti,baylor}!peter
IAEF: ...!kitty!baylor!peter

zben@umd5.UUCP (11/26/85)

In article <468@graffiti.UUCP> peter@graffiti.UUCP (Peter da Silva) writes:
In article ? ? writes:  [z]
>> I think the concept of DST is stupid, but so long as
>> it has to be dealt with, some means must be provided.
>
>Perhaps, perhaps, but it'd be better to leave that up to the application
>instead of stuffing the library or forcing some PC user to create a file
>at certain times of the year just to run some program that happens to be
>written in 'C'.   ...

Watch out people!  The latest proposal in Congress to keep elections from
being decided before the West Coast gets its chance to vote involves a bad
change to Daylight Savings Time!

As I read it in the Post yesterday, the proposal is to make the polling
places close at 7:00 EST, 8:00 CST, and extend Daylight Savings Time for the
West Coast two more weeks till election day!

The idea of changing the DST algorithm for a) West Coast sites only, and
b) only in an election year doesn't really turn me on AT ALL...  I think this
is a powerful argument for hiding the kluges in either a library routine or
the system.  Somewhere it can be setup when the system is configured, and not
have to be replicated in hundreds of programs.  If it is in the system, one
would not have to rebuild programs sent from elsewhere, while if it is in the
library one would at least have to re-link-edit.

Let's keep our eyes on this particular snake - it just might bite us all
someday...
-- 
Ben Cranston  ...{seismo!umcp-cs,ihnp4!rlgvax}!cvl!umd5!zben  zben@umd2.ARPA

gwyn@BRL.ARPA (VLD/VMB) (11/27/85)

The thing is, the raw "language" part of C is (by design)
insufficient for programming real hosted applications,
so it must be extended with some library routines.  The
de facto set of library routines is a subset of those
found in the UNIX C library.  Certainly STDIO is generally
agreed upon, but there is more interaction with the host
environment needed than just file I/O.  Since a large
number of non-UNIX C implementations have provided much of
the UNIX C library, and since most of those library routines
are well-designed, it makes sense to standardize their
interface, patterned after the original UNIX routines but
with redefinitions as required to accommodate a wide variety
of operating system environments.

The Software Tools "Virtual Operating System" approach was
very similar (although accessed from RatFor, not C), and
their routines were also closely modeled after UNIX's.
This by no means constrained implementation to just UNIX
and its lookalikes; the VOS ran on just about every major
operating system, from micros to mainframes.  I haven't
noticed any real UNIX dependencies in X3J11's proposed
standard library routines.  Virtually everything they have
included are routines I frequently use in applications.
This applies no less to my Apple //e than it does for UNIX
systems.  In the past I have implemented similar libraries
for RT-11 and RSTS/E, and DEC's VMS C compiler provides
pretty much the same functions.

I agree that the C language standard should be independent
of UNIX, but I think it already is.  I see no point in
splitting the standard up into pieces, since portable
applications will require these routines anyway.  With
only a few very minor quibbles, I am happy with the X3J11
proposed draft standard and its general applicability to
virtually any hosted environment.  (Of course, your compiler
vendor may have some work to do to conform, but that's true
in any case.)

time_t is NOT seconds, in Doc. No. X3J11/85-045 (dated
April 30, 1985).  It IS an "arithmetic type", which does
seem like an oversight, since arithmetic on it cannot be
done portably (and structures can be assigned, passed as
function parameters, etc. so all necessary operations
work without requiring arithmeticity).  I think the
oversight needs to be remedied in the final standard.

gwyn@BRL.ARPA (VLD/VMB) (11/27/85)

> "they took the entry for ctime from the third section of the UNIX
> manual and copied it verbatim"

Hey, get a current copy of the draft standard!  Since April,
the X3J11 spec for ctime has not very much resembled the one
in any UNIX manual.  If you want to criticize the committee's
work, you ought to find out what it is first.  I find that a
lot of thought has indeed been put into generality of the
time functions.

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (11/27/85)

> Watch out people!  The latest proposal in Congress to keep elections from
> being decided before the West Coast gets its chance to vote involves a bad
> change to Daylight Savings Time!
> 
> As I read it in the Post yesterday, the proposal is to make the polling
> places close at 7:00 EST, 8:00 CST, and extend Daylight Savings Time for the
> West Coast two more weeks till election day!

Better to close the polls before they open; maybe we could get rid
of the silly Congress eventually.

> The idea of changing the DST algorithm for a) West Coast sites only, and
> b) only in an election year doesn't really turn me on AT ALL...  I think this
> is a powerful argument for hiding the kluges in either a library routine or
> the system.

To me, it's a powerful argument for scrapping DST altogether.

laura@l5.uucp (Laura Creighton) (11/27/85)

In article <98@brl-tgr.ARPA> gwyn@BRL.ARPA (VLD/VMB) writes:
>
>Hey, get a current copy of the draft standard!

How?  I've sent electronic mail to Larry Rostler 3 times in the last
2 months.  Maybe he has been busy, and maybe ihnp4 had indigestion, but
I still don't have a current standard.

Is there any way that the draft standard could get posted to mod.std.c?
Or sent to John Quarterman (or someone, me even, but he seems a good
choice so that people could tftp it)?  I *hope* it exists in electronic
from somewhere...

-- 
Laura Creighton		
sun!l5!laura		(that is ell-five, not fifteen)
l5!laura@lll-crg.arpa

rbutterworth@watmath.UUCP (Ray Butterworth) (11/27/85)

  > gmtime(), like time(), ctime(), and localtime(), takes a
  > pointer to a time_t because that's what they already do.
  > These functions have been defined (in UNIX at least) for a
  > long time (no pun intended).

Simply because they have been around for a long time, doesn't
mean that they are the best way of doing things; and simply
because UNIX does it that way, doesn't mean that everyone else
should do it that way.  This is supposed to be a C standard,
not a make-the-world-look-like-UNIX standard.

I understand why they originally took pointers; but the need
is no longer there.  Now is the time to correct old mistakes
not propagate them.  A number of other functions are defined
by the standard that differ from the same functions on UNIX
(at least some versions of UNIX) and people are going to have
to make a number of changes to their code anyway.  It wouldn't
be that difficult for the standard to define these functions
with completely different names.  Systems that never had the
functions before can simply implement them as required, while
systems that have similar functions can either provide macros
or cover functions for mapping the one name and syntax into the
other until the general population gets used to the new names.
I know that for anything I write I already have a cover function
for ctime(), so that I can use ctime(time()) without having to
go through the bother of allocating a temporary variable that
I can take the address of.

  > difftime() accepts time_t arguments but returns a double.
  > Its result is expressed in SECONDS, whereas a time_t is not
  > necessarily expressed in seconds.  There is no portable way
  > to do simple arithmetic on general time_t values to produce
  > a time difference in seconds, hence difftime().

OK, this was my misreading of the standard.  The problem was that
it introduced CLK_TCK, clock_t, and time_t together, and it wasn't
obvious to me that CLK_TCK wasn't the conversion factor between the
two.  I wasn't the only one that made the same mistake.  There
really should be a note here that the meanings of the values of
time_t are implementation defined.

One of the biggest problems with the K&R C manual is the things
that it doesn't explicitly mention.  It often takes a student
of theological research to find the various hints and put them
together to make a definite rule.  Please don't make this new
standard work the same way.  i.e. don't leave the readers with
the idea that "if we didn't mention something, then you can do
what you want with it".  If something is implementation dependent
then the standard should explictly say so.  If something isn't
defined in the standard then we should assume that this was an
omission to be corrected in the future, not a deliberate loophole
that every implementor is free to interpret as he wishes.

  > Seems to me they put more thought
  > into it than some of their detractors..

True.  If I want to make a public fool of myself, that only
concerns me.  But if the standards are sloppy, then that is
everyone's business.  This is supposed to be a scientific
document giving precise rules; it isn't supposed to be the bible
for some religion of C-worshippers who will spend hours pondering
its mysteries and trying to interpret its hidden meanings.  Just
look at the articles that continually appear in this news group.
Far too many of them are discussions about what K&R really meant
when they said such-and-such, and proofs using quotations from
three different sections of the book to show what they really had
in mind.  Probably at least half of the articles in any year are
more or less identical with half the articles in any other year.
Wouldn't it be nice to have a document which explicitly tells us
how things are supposed to be instead of one which encourages such
time-wasting discussions?

mikeb@inset.UUCP (Mike Banahan) (11/28/85)

In article <468@graffiti.UUCP> peter@graffiti.UUCP (Peter da Silva) writes:
>The basic complaint is that X3J11 is not a description of 'C', but rather a
>description of 'C' under UNIX. There is a good deal of stuff in it that
>should not be in the language definition, but rather in a standard
>extension: the UNIX compatibility package, for example. I like UNIX, and
>I'd like nothing better than to see it become the standard O/S for non
>real-time applications (how does one deal with the DST in some little
>standalone 'C' program in an RTU in Oman somewhere? They don't even use
>it...), but I don't expect it to happen. I like 'C', and I sure hope that
>it doesn't become restricted to UNIX and UNIX-like systems.
>
>That's what I see happening, however, unless X3J11 is (a) ignored or (b)
>fixed. And I hope that if they don't (b) fix it, everyone else follows my
>example and (a) ignores it.

That's not too difficult to get around. What Peter is describing is
the `conforming hosted implementation'. He has missed the bit at the front
of the draft which says that a `conforming freestanding implementation'
doesn't have the libraries: you have to provide your own. It's more painful,
but you can write stand-alone code that way.

Interestingly, of course the libraries themselves MUST be prepared in a
freestanding fashion; it is explicitly forbidden to define a function
called `printf' in a hosted implementation!


Now some people would come back with the ``read the draft you dummy''
sort of flame - but that isn't why we should be using this newsgroup.
However, as one who has played a part in the drafting of the standard,
I must admit that it is *EXTREMELY ANNOYING* to see questions posted
which are based on the assumption that ``the committee are a bunch
of unthinking turkeys''. Postings of that sort are a good way of
	1) annoying those who know the answer, enough so they
	   don't reply.
and
	2) getting the usual raft of know-nothing replies from folk
	   who read an old draft once and now think that they understand it.

Believe it or not, most of the committee members know a great deal
about C, and care a lot about how the standard ends up. Every single
word in that document has been discussed, taken apart, shaken, and
put back if it fits. It's worth bearing that in mind if you come across
something that doesn't seem to make immediate sense; maybe you're missing
the point - there are some subtle problems which take some sorting out.

(Sorry Peter - that wasn't aimed at you personally, just a general chide).
-- 
Mike Banahan, Technical Director, The Instruction Set Ltd.
mcvax!ukc!inset!mikeb

rbutterworth@watmath.UUCP (Ray Butterworth) (11/28/85)

> > "they took the entry for ctime from the third section of the UNIX
> > manual and copied it verbatim"
> 
> Hey, get a current copy of the draft standard!  Since April,
> the X3J11 spec for ctime has not very much resembled the one
> in any UNIX manual.

But wasn't compatibility your reason for defending the retention
of the use of the pointer?  If it doesn't resemble the one in the
UNIX manual, does that mean that it is now ctime(time_t) instead
of ctime(time_t*)?  If not, how do you justify the "*"?

henry@utzoo.UUCP (Henry Spencer) (11/29/85)

> Simply because they have been around for a long time, doesn't
> mean that they are the best way of doing things; and simply
> because UNIX does it that way, doesn't mean that everyone else
> should do it that way.  This is supposed to be a C standard,
> not a make-the-world-look-like-UNIX standard.

This is supposed to be a C standard, not a make-the-world-look-the-way-
Ray-wants-it-to standard.  That means one uses existing conventions, even
if they are a bit silly, rather than gratuitously inventing new ones.
People implementing gmtime() have generally followed the Unix conventions.
Note that the pointer convention of gmtime() etc. doesn't actually hurt
anything; it is silly in a modern context, but that is not sufficient reason
to "fix" it and thus break every program that ever used it.

> I understand why they originally took pointers; but the need
> is no longer there.  Now is the time to correct old mistakes
> not propagate them.

Why, exactly, does this need fixing so badly?

> A number of other functions are defined
> by the standard that differ from the same functions on UNIX
> (at least some versions of UNIX) and people are going to have
> to make a number of changes to their code anyway.

Name three.  If you mean that the standard defines functions which are
preferable to the UNIX ones, and that UNIX programs should be redone to
use the new ones, that's a different story.  My information may be out
of date, but I'm not aware of *any* functions in the drafts I've seen
that are inconsistent with UNIX usage to the point of breaking code.
Not breaking existing legal code was a major objective of the committee!

> I know that for anything I write I already have a cover function
> for ctime(), so that I can use ctime(time()) without having to
> go through the bother of allocating a temporary variable...

I trust that you're being informal for the sake of explanation, rather
than claiming that you use the name "ctime" for your new function, or
that you call time() without a parameter (which is wrong).

> One of the biggest problems with the K&R C manual is the things
> that it doesn't explicitly mention...  Please don't make this new
> standard work the same way...If something is implementation dependent then
> the standard should explictly say so.

This is one of the reasons why writing the X3J11 drafts is much harder
work than writing appendix B of K&R -- there really is a major attempt to
be precise and complete.  But the standard really cannot say "the values
of CLK_TIM and BUFSIZ are unrelated even though one happens to be ten times
the other" (to pose a silly hypothetical case); it is impractical to
disclaim everything, the document becomes unreadable.  People using the
language must rely on what the standard says and *not* rely on what it
doesn't say.  The best the standards-writers can do is to make the more
obvious and conspicuous non-relationships explicit.  Note also that the
words "implementation-dependent" in an X3J11 draft have a specific meaning:
they mean that the implementor can make the decision as he wishes BUT IT
MUST BE DOCUMENTED.
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (11/29/85)

> I understand why they originally took pointers; but the need
> is no longer there.  Now is the time to correct old mistakes
> not propagate them.  A number of other functions are defined
> by the standard that differ from the same functions on UNIX
> (at least some versions of UNIX) and people are going to have
> to make a number of changes to their code anyway.  It wouldn't
> be that difficult for the standard to define these functions
> with completely different names.

I suspect it was much easier to get the committee members to
all agree on an acceptable definition that covered the functions
already in use than it would be to get them to agree upon totally
new interfaces to the time functions.  Pointer parameters are not
necessarily a "mistake", although they are not the best way to
design these functions if one were to do so TODAY.  The job of
porting applications forward to the new X3J11 environment is much
easier if it is compatible with the current (poorly defined) one.

The fact of the matter is, most good commercial implementations of
non-UNIX C provided UNIX-compatible library routines all along.
The most notable exception was Whitesmiths, Ltd., and even then
one could get a UNIX-compatible library from Plum Hall, Inc.  The
X3J11 standard is just defining what an application shall be able
to count on in all conforming environments; those of us who have
been hauling around our own C libraries will be glad to have them
provided for us uniformly across all systems.

> There really should be a note here that the meanings of the
> values of time_t are implementation defined.

Some clarification might indeed be helpful.  The meaning of time_t
data lies in how they are used, which the library function
definitions explain.

> One of the biggest problems with the K&R C manual is the things
> that it doesn't explicitly mention.  It often takes a student
> of theological research to find the various hints and put them
> together to make a definite rule.  Please don't make this new
> standard work the same way.  i.e. don't leave the readers with
> the idea that "if we didn't mention something, then you can do
> what you want with it".  If something is implementation dependent
> then the standard should explictly say so.  If something isn't
> defined in the standard then we should assume that this was an
> omission to be corrected in the future, not a deliberate loophole
> that every implementor is free to interpret as he wishes.

X3J11 has nicely addressed most of the ambiguities and omissions
in K&R.  I think it is implicit in any such standard that whatever
has not been defined in the standard has no guarantees of any kind.
There are uncountably more things not explicitly addressed by the
standard than are addressed; it would be infeasible to anticipate
them all.  If you can identify some specific items that need to be
addressed you should bring them to the attention of the X3J11
committee ASAP.

I believe the intent is to specify no more and no less than the
rules that MUST be followed by a conforming implementation.  This
implies that anything not specified must NOT be relied on by
portable applications code.  One need not guess.

> This is supposed to be a scientific
> document giving precise rules; it isn't supposed to be the bible
> for some religion of C-worshippers who will spend hours pondering
> its mysteries and trying to interpret its hidden meanings.

Agreed, except that "scientific document" is putting it too strongly.
The standard represents a consensus of experts, and as such has
compromises (like not insisting on the ASCII character set) and
weaknesses (like not providing for variable dimensions on formal
array parameters).  What one hopes is that it will be "good enough"
to promote a uniform C environment.  My feeling is that it will be.

Actually, K&R wasn't too bad, but one had to THINK and UNDERSTAND
the ideas and "spirit" of the C language, and a lot of people
obviously had trouble in these areas.  X3J11 is much more explicit.

> Just look at the articles that continually appear in this news group.
> Far too many of them are discussions about what K&R really meant
> when they said such-and-such, and proofs using quotations from
> three different sections of the book to show what they really had
> in mind.  Probably at least half of the articles in any year are
> more or less identical with half the articles in any other year.
> Wouldn't it be nice to have a document which explicitly tells us
> how things are supposed to be instead of one which encourages such
> time-wasting discussions?

Exactly.  BUT don't expect that to stop idiotic postings to the
news group.  Many of them in the past could have been resolved
by reading VERY CLEAR statements in K&R, but the posters didn't
bother to look them up.

I think part of the problem is that people are getting incorrect
explanations from sources such as amateur hacker journals (and
even this newsgroup!), and they don't realize that people
propagating bogus information don't know what they're talking
about.  There is a lot of "unlearning" to be done if one has
acquired C "knowledge" from such sources.

gwyn@BRL.ARPA (VLD/VMB) (11/30/85)

There is a BIG difference between "taking the entry for ctime
from the UNIX manual and copying it verbatim" and the fact
that ctime takes a (time_t *) argument!  The former was being
accused of X3J11 as an argument that they had not done any
thinking about the time functions; that is totally wrong.  The
latter is the result of the desire not to break a large base
of existing code.  These are NOT the same issue.

howard@cyb-eng.UUCP (Howard Johnson) (12/04/85)

> As I read it in the Post yesterday, the proposal is to make the polling
> places close at 7:00 EST, 8:00 CST, and extend Daylight Savings Time for the
> West Coast two more weeks till election day!
> 
> The idea of changing the DST algorithm for a) West Coast sites only, and
> b) only in an election year doesn't really turn me on AT ALL...  I think this
> is a powerful argument for hiding the kluges in either a library routine or
> the system.  Somewhere it can be setup when the system is configured, and not
> have to be replicated in hundreds of programs.  If it is in the system, one
> would not have to rebuild programs sent from elsewhere, while if it is in the
> library one would at least have to re-link-edit.

I can just see localtime() scanning a file (perhaps /etc/dst) to figure out
whether or not Daylight Savings Time is in effect.

This is yet another application crying out for some kind of dynamic
link editor.  (Hmmm, sounds like this could be cross-posted to net.os...)
-- 
..!{seismo,topaz,mordor,harvard,gatech,nbires,ihnp4}!ut-sally!cyb-eng!howard
(ordered best to worst); also ..!ut-ngp!cyb-eng!howard  +1 512 835-2266

peter@baylor.UUCP (Peter da Silva) (01/18/86)

> difftime() accepts time_t arguments but returns a double.

What's wrong with returning a long?

What's wrong with having a function:

long seconds(time)
time_t time;

Really much more generally useful, you know.

But, mainly, returning a double means loading in the floating point package.
On a lot of machines doing any floating point arithmetic in a program adds
quite a bit of overhead. Returning a long would be much more reasonable.
-- 
-- Peter da Silva
-- UUCP: ...!shell!{baylor,graffiti}!peter; MCI: PDASILVA; CIS: 70216,1076

peter@baylor.UUCP (Peter da Silva) (01/18/86)

> For example (not necessarily optimum), DST could be
> indicated by the presence of a specific system file.
> The implementation of gmtime() would test for this
> (the first time it is called within the process).

Boy. You're assuming a lot about a system. Let's say we're doing a IBM-PC
implementation. And we want the whole program to fit into a single file
because otherwise nobody's going to buy it. And we don't want people to
have to create weird files all over the place because then we get really
bad reviews. What are we supposed to do? Ask the user for the current time
zone every time we run? Create a random file called timezone? Boy, will
that help us sell the software. Gee, the user asks, why did I bother
buying this real-time-clock card.

Basically, X3J11 seems to assume, at a minimum, a minicomputer or supermicro
with a hard disk and a guru to create special files all over the place.

> I think the concept of DST is stupid, but so long as
> it has to be dealt with, some means must be provided.

I'm saying that on most small machines it doesn't have to be dealt with, and
has no place in a generally useful standard.
-- 
-- Peter da Silva
-- UUCP: ...!shell!{baylor,graffiti}!peter; MCI: PDASILVA; CIS: 70216,1076

tj@alliant.UUCP (Tom Jaskiewicz) (01/23/86)

In article <618@baylor.UUCP> peter@baylor.UUCP (Peter da Silva) writes:
>> difftime() accepts time_t arguments but returns a double.
>
>What's wrong with returning a long?

1.  time_t may give millisecond resolution (or microseconds (or nanoseconds))
which you really want to have.

2.  difftime may need to return a value larger than 2**32 (not likely but
possible).

In short, you want the range that floating point provides for you.

>What's wrong with having a function:
>
>long seconds(time)
>time_t time;

Nothing really.  But I would rather use difftime *unless* I had a good
reason not to, such as running on a machine where

>doing any floating point arithmetic in a program adds
>quite a bit of overhead.
-- 
####################################################################
# uucp:  decvax!linus!alliant!tj ## Bernese are mountains of love. #
####################################################################

msb@lsuc.UUCP (Mark Brader) (01/23/86)

> > difftime() accepts time_t arguments but returns a double.

> What's wrong with returning a long?
> 
> What's wrong with having a function:
> 
> long seconds(time)
> time_t time;

What's wrong is that some non-UNIX systems may wish to keep their
internal times based on an origin that is much earlier than UNIX's
start-of-1970-GMT.  Then a time in seconds-since-origin won't fit
in a long.

Mark Brader

hand@ncsu.UUCP (Steven Hand) (02/06/86)

By the way, can anyone send me the details on how to order the
ANSI C reference manual?

Thanks, Steve

karl@haddock (08/13/86)

ANSI C folks, please take note.

I've found some questionable things in the May, 1986 draft that I'd like to
open up for discussion by the net.  (I don't have a more recent copy, or even
know if there is one; my apologies if some of these issues have already been
closed.)

In 3.2.2.3, "(void *)0" is called a null pointer constant, though 5.6.3.12
says the value of NULL is implementation-defined.  I take this to mean that
the internal representation of (void *)0 need not have all bits clear.  The
constant 0 used in a pointer context still denotes the null pointer, but an
integer variable whose value happens to be zero need not produce the null
pointer when cast.  Also, if I have a pointer variable whose value happens
to be NULL and I cast it into int, I'll likely get the internal form (what
I'd get if I used a union) rather than zero as a result, right?  In boolean
context ("if (p)"), there is an implied comparison with NULL, not an implied
cast to int.  (In the above, I am assuming sizeof(int) == sizeof(void *).)
Do I have this right?

In 3.3.3 and 3.3.4, we find the definitions of _u_n_a_r_y_-_e_x_p_r_e_s_s_i_o_n and _c_a_s_t_-\
_e_x_p_r_e_s_s_i_o_n.  Wouldn't it have been simpler to define cast to be a unary
operator?  (That's the way *I* always think of it.)  In other words, it seems
one could add "( _t_y_p_e_-_n_a_m_e ) _u_n_a_r_y_-_e_x_p_r_e_s_s_i_o_n" to the 3.3.3 syntax and move
section 3.3.4 to 3.3.3.x.  Am I overlooking something?

In 4.2.1.1: "If NDEBUG is defined ... use of the assert macro will have no
effect."  This needs to be clarified as follows: "The expression {shall|may|
shall not} be evaluated for side effects."  (Consider e.g. "assert(getchar()\
==EOF)", for example.)  The UNIX* version currently does not evaluate it; it
sometimes would be more useful if it did.  In any case the ambiguity needs to
be resolved.

In 4.7.1.1, we see that all signals are initialized to SIG_DFL, a surprising
contrast to the way things currently work on UNIX, where signals can be set
to ignore (by nohup(1) or other means) before the program starts.  I see two
interpretations:

    [a] SIG_DFL means "die on this signal"; programs like nohup can no longer
	be written.

    [b] If nohup presets the signal to be ignored, then for the duration of
	the program exec'd from it, SIG_DFL means "ignore this signal".

The first interpretation is clearly a problem.  The second is more subtle.  I
think "if (signal(SIGINT, SIG_IGN) == SIG_IGN) signal(SIGINT, trap);" would
now be broken, because the first signal() will return SIG_DFL rather than
SIG_IGN.

In 4.9.3: "When opened, the standard streams are fully buffered if and only
if the stream does not refer to an interactive device."  So, stderr isn't a
special case anymore?  (It's currently unbuffered.)

In 4.9.6.1 and 4.9.6.2 (fprintf and fscanf), it says that any conversion
specifier other than those listed results in undefined behavior if it's a
lower-case letter, otherwise implementation-defined behavior.  In other
words, the lower-case letters are reserved for future official releases, and
the other characters are reserved to the implementation.  This is a bad idea.
Note that the flag characters occupy the same "namespace" as the conversion
specifiers; future non-alphabetic flags could potentially clash with some
implementation's conversion specifier.  I suggest that there should be *one*
character reserved for the implementation, which can be used as a prefix.
E.g. if I want my library to have a binary-output format, I could then use
"%&b" if "&" is the prefix.  Sort of like a run-time #pragma.

In 4.9.6.2, the documentation for the "[" conversion specifier (which scans a
string not delimited by white space) fails to mention a range syntax, but the
example on the next page uses "%[0-9]".  Also, it fails to mention whether
one can include a right-bracket in the scanset; most implementations allow
it as the first character (following the "^", if any).  (Unless they want to
allow an empty scanset, in which case *that* should be documented.)

In 4.10.4.4, we see that any function (presumably the user's) which is
registered by onexit() should take zero arguments and return a value of type
onexit_t.  No mention is made of what this return value should be, or who
will look at it.  The function onexit() itself returns type onexit_t, but the
only comment is that it "compares equal to a null pointer constant" if it
succeeds.  (Aha, so onexit_t must be some kind of pointer!)  If the user is
only expected to test for success/failure, why not just return an int?  It
seems to me that this could have been declared "int onexit(void (*)(void))",
omitting the onexit_t stuff completely.

But, back in 4.10 it was claimed that onexit_t "is the type of both the
argument to and the value returned by the onexit function".  One wonders if
"argument to [onexit]" should have been "result of the function pointed to by
the argument to [onexit]".  If not, and we take it literally, we conclude
that "onexit_t" is a synonym for "onexit_t (*)(void)", an undeclarable type.
Someone hinted at this some months ago in an earlier posting, so maybe it's
true.  But why?

Finally, in 5.1.3 we have a really serious error :-).  "#error" and "#pragma"
are listed in the wrong font.

Karl W. Z. Heuer (ihnp4!ima!haddock!karl), The Walking Lint
*UNIX is a trademark of AT&T Bell Laboratories.

guy@sun.uucp (Guy Harris) (08/14/86)

> In 3.2.2.3, "(void *)0" is called a null pointer constant, though 5.6.3.12
> says the value of NULL is implementation-defined.  I take this to mean that
> the internal representation of (void *)0 need not have all bits clear.

Yes.  I'm certain there are many machines out there that either have C
implementations or should have them that have a representation for null
pointers that is not a bucket of zero bits.

> The constant 0 used in a pointer context still denotes the null pointer,
> but an integer variable whose value happens to be zero need not produce
> the null pointer when cast.

Yes.  This may be considered questionable, since, given the declarations

	int i;
	char *p;

the statements

	i = 1; p = i;

and

	p = 1;

should be expected to stuff the same value into "p", but the statements

	i = 0; p = i;

and

	p = 0;

need not stuff the same value into "p" - i.e., the constant expression 0 is
treated differently when converting to a pointer type than any other
integral expression.  Unfortunately, there's not a hell of a lot you can do
about it.  If C had a keyword "nil" that would, when it appears in an
expression, be converted to a null pointer of the appropriate type (as the
constant expression 0 is converted now), this problem wouldn't occur;
however, it's a little to late to fix this now, given all the code out there
that uses 0 for this.

"Fixing" it the other way, by having any integral expression with the value
0 convert to a null pointer, would 1) add some extra inefficiency to
integer-to-pointer conversions on machines with special null pointer
representations without much benefit (if any), and 2) surprise some code
that does want to grab a pointer value, fiddle the bits (setting a ring
number, for instance) and then stuff the value back into the pointer, if a
pointer value of all zero bits is a valid pointer.

> Also, if I have a pointer variable whose value happens to be NULL and I
> cast it into int, I'll likely get the internal form (what I'd get if I
> used a union) rather than zero as a result, right?

Right.

> In boolean context ("if (p)"), there is an implied comparison with NULL,
> not an implied cast to int.

Actually, it's an implied comparison with 0; however, the 0 has to get
converted to the type of "p", so that the effect is the same as
"if (p == 0)", namely that "p" gets compared with a null pointer.
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com (or guy@sun.arpa)

msb@dciem.UUCP (Mark Brader) (08/15/86)

Somebody writes:

> > In 3.2.2.3, "(void *)0" is called a null pointer constant, though 5.6.3.12
> > says the value of NULL is implementation-defined.  I take this to mean that
> > the internal representation of (void *)0 need not have all bits clear.

Guy Harris (guy@sun.uucp) replies:

> Yes.  I'm certain there are many machines out there that either have C
> implementations or should have them that have a representation for null
> pointers that is not a bucket of zero bits.

This is almost correct.  It IS true that (void *)0 need not have all bits
clear, but this is not what the reference in 5.6.3.12 is saying.  What it is
saying is that your implementation can #define NULL as either 0 or (void *)0.

Mark Brader, dciem!msb
#define	MSB(type)	(~(((unsigned type)-1)>>1))

karl@haddock (08/16/86)

haddock!karl (Karl Heuer) writes:
>> The constant 0 used in a pointer context still denotes the null pointer,
>> but an integer variable whose value happens to be zero need not produce
>> the null pointer when cast.

sun!guy (Guy Harris) replies:
>Yes.  This may be considered questionable, since, given the declarations
>"int i; char *p;" the statements "i=1; p=i;" and "p=1;" should be expected
>to stuff the same value into "p", but the statements "i=0; p=i"; and "p=0;"
>need not stuff the same value into "p" - i.e., the constant expression 0 is
>treated differently when converting to a pointer type than any other
>integral expression.

In particular, "p = i = 0;" is a loser!  (I don't expect many programs do
this, since it produces a pointer/integer conflict.)

>Unfortunately, there's not a hell of a lot you can do about it.  If C had a
>keyword "nil" that would, when it appears in an expression, be converted to
>a null pointer of the appropriate type (as the constant expression 0 is
>converted now), this problem wouldn't occur; however, it's a little to late
>to fix this now, given all the code out there that uses 0 for this.

It's not too late.  In the first place, NULL already exists for this purpose
(though some people insist on using it as a synonym for '\0' too!)  If zero-
in-pointer-context henceforth produces a warning message, people will convert
their programs to use NULL instead.  If the feature then goes away, only the
programmers who ignored the warning will be burned.  (This is not necessarily
a good idea, but it *can* be done.)  NULL would presumably be changed from
"0" to an implementation-defined constant like "(void *)0xF0000000".

>"Fixing" it the other way, by having any integral expression with the value
>0 convert to a null pointer, would ... surprise some code that does want to
>grab a pointer value [as int] and then stuff the value back into the
>pointer, if a pointer value of all zero bits is a valid pointer.

Hmm, there's a similar problem without the full-check conversion.  If the
constant zero is converted into a null pointer constant, and zero is a valid
address, and something of interest is at that absolute address, how do I
reference it?  "x = *(int *)0" will try to dereference NULL instead of 0, and
"i = 0; x = *(int *)i" will undoubtable fail on some optimizing compilers.

Karl W. Z. Heuer (ihnp4!ima!haddock!karl), The Walking Lint

guy@sun.uucp (Guy Harris) (08/16/86)

> It's not too late.  In the first place, NULL already exists for this purpose
> (though some people insist on using it as a synonym for '\0' too!)  If zero-
> in-pointer-context henceforth produces a warning message, people will
> convert their programs to use NULL instead.  

Yes, but I don't know whether the disruption that would cause at this late
date would be worth the advantages the changes you suggest would bring.

	1) I've seen a fair amount of code that does things like

		<something> *p;
		...
		if (p == 0)

	(which is perfectly legitimate and type-correct C) and makes
	calls like

		execl("/bin/cat", "cat", "file", (char *)0);

	2) What happens to code like

		<something> *p;
		...
		if (p)

	or
		if (!p)

	which is also, at least by my interpretation of the August 11,
	1985 ANSI C draft, perfectly legitimate and type-correct C.
	The discussions of Boolean objects (now that Root Boy is gone,
	I guess we can acknowledge the existence of Boolean objects in
	C again) in the draft talk use terms like "equals 0" or "does
	not equal 0"; I presume some expression X "equals 0" iff X == 0,
	and "does not equal 0" iff X != 0.  Both of those comparisons
	can be done on pointers.


The code in both these examples will have to be changed.  The ANSI C
committee is at least trying not to break existing code any more than is
absolutely necessary.

> NULL would presumably be changed from "0" to an implementation-defined
> constant like "(void *)0xF0000000".

Blech!  I suppose the compiler will recognize expressions like that and, if
it treats null pointers in any special way, will treat them as such, but it
seems ugly.  (Yes, a compiler *could* treat them in usefully special ways.
For instance, it might try to do dataflow analysis and figure out whether
you run the risk of dereferencing a NULL pointer or not.  Said dataflow
analysis would have to be interprocedural, of course, and cross module
boundaries; however, given the depressing amount of crap code out there that
is careless about null pointers, it might be worth it.)

> Hmm, there's a similar problem without the full-check conversion.  If the
> constant zero is converted into a null pointer constant, and zero is a valid
> address, and something of interest is at that absolute address, how do I
> reference it?  "x = *(int *)0" will try to dereference NULL instead of 0,
> and "i = 0; x = *(int *)i" will undoubtable fail on some optimizing
> compilers.

Why?  If the compiler implements C, it will NOT combine the two statements
into one, since the meaning of "x = *(int *)0" is undefined, but the meaning
of "x = *(int *)i" is defined to the extent that conversions of "int" to
"int *" is defined.  The optimizer might decide that the value of "i" is
known at that point, and compute the value of "(int *)0" at compile time,
and generate code to load the "int" value that would be located at that
address into "x".  It might then discover that "i" is dead at that point,
and throw it away.  No C compiler will generate code to dereference a null
pointer for that example; any compiler that does is compiling a language
other than C.
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com (or guy@sun.arpa)

faustus@ucbcad.BERKELEY.EDU (Wayne A. Christopher) (08/18/86)

If there is a compiler that defines NULL as something other than an
all-0 bit pattern, I certainly hope that "if (!p)" will do the right
thing, otherwise most existing code won't work.  But this should never be
a real problem, since all the loader has to do is guarantee that
nothing valid will ever have an address that corresponds to the
conversion of integer 0 to a pointer.  There are no architectural
considerations involved -- if there are tag bits, etc, just let them be
all 0 -- the pointer should never be referenced anyway, so who cares
what the tag bits are.

In article <86900017@haddock>, karl@haddock writes:
> > "Fixing" it the other way, by having any integral expression with the value
> > 0 convert to a null pointer, would ... surprise some code that does want to
> > grab a pointer value [as int] and then stuff the value back into the
> > pointer, if a pointer value of all zero bits is a valid pointer.

You can always use a union, or cast a pointer to the needed value -- these
tricks are used for things like dissecting floating point numbers.

> Hmm, there's a similar problem without the full-check conversion.  If the
> constant zero is converted into a null pointer constant, and zero is a valid
> address, and something of interest is at that absolute address, how do I
> reference it? 

If there is something of interest at location 0 then you should complain to
whomever put it there.  It's a very good idea to make null pointer references
cause a fault -- this catches lots of nasty bugs.  If this isn't the case
on your machine, you can still use the tricks mentioned above.

	Wayne

ron@brl-sem.ARPA (Ron Natalie <ron>) (08/21/86)

In article <971@ucbcad.BERKELEY.EDU>, faustus@ucbcad.BERKELEY.EDU (Wayne A. Christopher) writes:
> If there is something of interest at location 0 then you should complain to
> whomever put it there.  It's a very good idea to make null pointer references
> cause a fault -- this catches lots of nasty bugs.  If this isn't the case
> on your machine, you can still use the tricks mentioned above.
> 
Even the PDP-11's used to put a zero on the split-I/D images at zero to
assure there wasn't anything useful at zero.  Unfortunately, people learned
to rely on this.  I suspect we might not have had as much problems if VAX's
and PDP-11's had something useless like at "setd" instruction at the bottom
of their dataspaces

-Ron (p&P6) Natalie

bzs@bu-cs.BU.EDU (Barry Shein) (08/22/86)

An amusing anecdote on NULL pointers:

On our large IBM system an early version of one of the screen editors
had a null pointer problem. Basically, it would load the contents of
address 0 into a register rather than a zero.

Of course, the contents of location zero was zero. Usually.

Address zero on an IBM is the Machine Check PSW double-word. This
will contain the PSW if a machine check recently occurred (PSW is
the combined processor status, program counter, machine check means
a detected hardware error, obviously not fatal or why put it there.)

You guessed it! Mysterious failures of the editor as address 0
contained non-zero values for fleeting microseconds after a machine
check, which was a rare event. I guess the area got re-zeroed after
the O/S logged the error (or whatever.) It handled the machine check
asynchronously (maybe this was really caused by the dual processors,
I don't remember.)

Fun fun. Kids, our lives were already ruined by this sort of self-abuse,
but you're young, you can be saved, ah youth, wasted on the young :-)

	-Barry Shein, Boston University