peter@graffiti.UUCP (Peter da Silva) (11/18/85)
I finally got hold of a copy of the new proposed standard (thanks Stanley!), and would like to point out a problem with it: it's a prescriptive rather than a descriptive standard. Now I know ANSI has acquired a habit of making prescriptive standards lately, but at least there had been a pre-existing descriptive standard to work from. Oh well. I would also like to point out that there are several UNIX-like functions in the library that are inappropriate for most non-UNIX implementations of 'C'. In particular, the time functions (ctime(3) in the UPM) are unimplementable in many systems, due to the lack of a daylight savings flag in the O/S. Would it be acceptable to seperate O/S and language library functions so that non UNIX environments can support ANSI-C? Finally, if \v is to produce a vertical tab, does that require the I/O library to include termcap so that the various output devices that implement this function in various ways can be accomodated? Basically, the standard is far too specific... it prescribes actions that are strictly outside the definition of the language. -- Name: Peter da Silva Graphic: `-_-' UUCP: ...!shell!{graffiti,baylor}!peter IAEF: ...!kitty!baylor!peter
ron@brl-sem.ARPA (Ron Natalie <ron>) (11/18/85)
> I finally got hold of a copy of the new proposed standard (thanks Stanley!), > and would like to point out a problem with it: it's a prescriptive rather > than a descriptive standard. Now I know ANSI has acquired a habit of making > prescriptive standards lately, but at least there had been a pre-existing > descriptive standard to work from. Oh well. Crapola, ANSI standards are almost always based on some existing work. But anything that's done by committee is likely to get riddled with a lot of self interests. > I would also like to point out that there are several UNIX-like functions in > the library that are inappropriate for most non-UNIX implementations of 'C'. > In particular, the time functions (ctime(3) in the UPM) are unimplementable > in many systems, due to the lack of a daylight savings flag in the O/S. Would > it be acceptable to seperate O/S and language library functions so that non > UNIX environments can support ANSI-C? Eh? The timezone never belonged in the operating system! Unix time is GMT. Most versions of UNIX these days use an environment variable to convey timezone information to the user process. All the C environment needs to know is how to convert from GMT and LOCAL time to whatever the system uses for time and back. If you can't do this, it's likely to be impossible to use times in C at all, regardless of how CTIME is specified. > > Finally, if \v is to produce a vertical tab, does that require the I/O library > to include termcap so that the various output devices that implement this > function in various ways can be accomodated? Vertical TAB is an ASCII character. If the terminal doesn't support it, who cares. Some terminals don't do horizontal tab either, you want to pull \t? My model37 won't do \r either. -Ron
atbowler@watmath.UUCP (Alan T. Bowler [SDG]) (11/20/85)
In article <538@brl-sem.ARPA> ron@brl-sem.ARPA (Ron Natalie <ron>) writes: > >Eh? The timezone never belonged in the operating system! Unix time is GMT. >Most versions of UNIX these days use an environment variable to convey >timezone information to the user process. All the C environment needs to >know is how to convert from GMT and LOCAL time to whatever the system uses >for time and back. If you can't do this, it's likely to be impossible to >use times in C at all, regardless of how CTIME is specified. > The original problem still stands. The ANSI standard is specifying that a library function be able to produce a value that is not available on a large number of systems. No one really questions that Unix was right in deciding to store system time in GMT and make available information to compute some appropriate "local" time from GMT data. However, believe it or not there are non-Unix environments out there. No matter what the standard says, many operating systems do not have environment variables, and many of them do not keep time as GMT. The only time function supplied by the operating system effectively returns the value on the wall clock beside the operator's console. There is no available hint about the relation between this, and GMT or whether it is daylight savings time or not. The standard has no real business specifying the environment in this amount of detail, or perhaps it should be worded with something like "If you are going to supply XXXX functionality, do it like this...". I can live with the GETENV description since nothing stops me from just defining a GETENV that always returns NULL. I can't really live with the requirement that I supply routines LOCALTIME, and GMTIME since both require me to return information that is not available to me.
rbutterworth@watmath.UUCP (Ray Butterworth) (11/20/85)
> The standard has no real business specifying the environment in this > amount of detail, or perhaps it should be worded with something like > "If you are going to supply XXXX functionality, do it like this...". The standard obviously didn't put much thought into anything related to times. They define type "time_t" as an arithmetic type that represents the time, and then define a difftime(time_t time1,time_t time2) that computes the difference between these two arithmetic values. Why the function? Does the standard have a new arithmetic type on which the operation of subtraction is not allowed? And then they define a function gmtime(const time_t *timer) that takes a pointer to the arithmetic value, which it is not going to change anyway. Why not just take the value itself instead of the pointer?
peter@graffiti.UUCP (Peter da Silva) (11/21/85)
> Crapola, ANSI standards are almost always based on some existing work. But > anything that's done by committee is likely to get riddled with a lot of > self interests. And you don't see this as a problem? > > in many systems, due to the lack of a daylight savings flag in the O/S. Would > Eh? The timezone never belonged in the operating system! Unix time is GMT. Ctime(3) includes the definition of struct tm. This has been included bodily in the X3J11 library. The structure includes an element "tm_isdst", which is true if daylight savings time is currently active. This does NOT belong in a language standard. > > Finally, if \v is to produce a vertical tab, does that require the I/O library > > to include termcap so that the various output devices that implement this > > function in various ways can be accomodated? > > Vertical TAB is an ASCII character. If the terminal doesn't support it, The definition of the 'C' character set doesn't mention ASCII. It merely says that '\v' should advance to the next vertical tab mark. Immediately before this there are included a whole series of escape sequences that seem adequate to write 'C' programs in CDC 64-character code. At the very least the language is clumsy. -- Name: Peter da Silva Graphic: `-_-' UUCP: ...!shell!{graffiti,baylor}!peter IAEF: ...!kitty!baylor!peter
lr@sftig.UUCP (L.Rosler) (11/21/85)
> > The standard has no real business specifying the environment in this > > amount of detail, or perhaps it should be worded with something like > > "If you are going to supply XXXX functionality, do it like this...". > > The standard obviously didn't put much thought into anything related to > times. They define type "time_t" as an arithmetic type that represents > the time, and then define a difftime(time_t time1,time_t time2) that > computes the difference between these two arithmetic values. Why the > function? Does the standard have a new arithmetic type on which the > operation of subtraction is not allowed? > And then they define a function gmtime(const time_t *timer) that takes > a pointer to the arithmetic value, which it is not going to change anyway. > Why not just take the value itself instead of the pointer? Several members of the X3J11 Committee are working on a rationale document that will, I hope, clarify some apparently obscure choices. It happens that a great deal of thought went into every aspect of this issue. The first question was whether methods of determining and reporting time belonged in the C standard at all, or were properly part of a system-interface standard such as that being produced by IEEE P1003 (nee /usr/group). It was decided that the functionality desired was sufficiently widely available to warrant standardization in the language. Provisions were made for environments that didn't have the capability, by specifying a suitable error return which the application could check for (the same value as that used by UNIX*, not by coincidence). The second question, the need for inventing difftime(), was based on the concept that though the value returned by time() had to be arithmetic (in order that the error value, (time_t)-1, be easily detected), there was no need to burden implementations by requiring it to be a linear representation of the time, as it happens to be on UNIX systems. It need not even be monotonically increasing, viewed as an integer! The question of appropriate units for the difference of two times was finessed by specifying the result of the subtraction as a double, catering for resolutions of integer seconds on slow systems or nanoseconds on CRAYs. The third question, why accept a pointer argument instead of the value itself, reflects the encrustation of UNIX archaisms on a standard of this kind. In olden times, before C even had a "long" data type, the time was stored in an array of two 16-bit ints, hence HAD to be moved around via a pointer. (Remember that the name of the array serves as a pointer to the first element.) This is why time_t time(time_t *timer) can return a value via a side-effect on an argument. As a C function cannot return an array, originally this was the ONLY way time() could produce a result. When "long" was introduced, old programs continued to operate through the type mismatch, provided the order of the int's in the array was suitable to produce a "long". The time() function thus acquired a legitimate return value, and the side-effect was conserved for compatibility. No one on the Committee is PROUD of this kind of specification, nor would we design such functions that way ab initio. But one of the roles of rational standardization is to preserve what is, not create what should be. Thanks for your indulgence. We really do think hard on occasion. Larry Rosler, AT&T Editor, X3J11 C Standards Committee (201) 522-5086 * UNIX is a trademark of AT&T.
ark@alice.UucP (Andrew Koenig) (11/21/85)
> The standard obviously didn't put much thought into anything related to > times. They define type "time_t" as an arithmetic type that represents > the time, and then define a difftime(time_t time1,time_t time2) that > computes the difference between these two arithmetic values. Why the > function? Does the standard have a new arithmetic type on which the > operation of subtraction is not allowed? > And then they define a function gmtime(const time_t *timer) that takes > a pointer to the arithmetic value, which it is not going to change anyway. > Why not just take the value itself instead of the pointer? gmtime takes a pointer rather than the value itself for historical reasons. Before C had long integers, gmtime() took an array of two integers as its argument. Since C does not pass arrays by value, gmtime() actually saw a pointer.
lr@sftig.UUCP (L.Rosler) (11/22/85)
> In article <538@brl-sem.ARPA> ron@brl-sem.ARPA (Ron Natalie <ron>) writes: > > > >Eh? The timezone never belonged in the operating system! Unix time is GMT. > >Most versions of UNIX these days use an environment variable to convey > >timezone information to the user process. All the C environment needs to > >know is how to convert from GMT and LOCAL time to whatever the system uses > >for time and back. If you can't do this, it's likely to be impossible to > >use times in C at all, regardless of how CTIME is specified. > > > The original problem still stands. The ANSI standard is specifying that > a library function be able to produce a value that is not available on > a large number of systems. No one really questions that Unix was right > in deciding to store system time in GMT and make available information > to compute some appropriate "local" time from GMT data. However, > believe it or not there are non-Unix environments out there. No matter > what the standard says, many operating systems do not have environment > variables, and many of them do not keep time as GMT. The only time > function supplied by the operating system effectively returns the value on > the wall clock beside the operator's console. There is no available hint > about the relation between this, and GMT or whether it is daylight > savings time or not. > The standard has no real business specifying the environment in this > amount of detail, or perhaps it should be worded with something like > "If you are going to supply XXXX functionality, do it like this...". Perhaps it is unrealistic to expect people who state what the "ANSI standard is specifying" to have read it. The draft actually says, "The gmtime function returns ... a null pointer if GMT is not available." The presumption is that if the time() function works at all (see my previous posting on THAT subject), then it is reasonable to expect localtime() to work also. If gmtime() is available, it must work as specified; otherwise it fails in a specified way. In other words, "If you are going to supply gmtime functionality, do it like this...". > I can live with the GETENV description since nothing stops me from > just defining a GETENV that always returns NULL. I can't really live > with the requirement that I supply routines LOCALTIME, and GMTIME > since both require me to return information that is not available to me. But they don't. Larry Rosler, AT&T Editor, X3J11 C Standards Committee (201) 522-5086
seifert@hammer.UUCP (Snoopy) (11/22/85)
In article <170@watmath.UUCP> atbowler@watmath.UUCP (Alan T. Bowler [SDG]) writes: >In article <538@brl-sem.ARPA> ron@brl-sem.ARPA (Ron Natalie <ron>) writes: >> >>Eh? The timezone never belonged in the operating system! Unix time is GMT. >>Most versions of UNIX these days use an environment variable to convey >>timezone information to the user process. All the C environment needs to >>know is how to convert from GMT and LOCAL time to whatever the system uses >>for time and back. If you can't do this, it's likely to be impossible to >>use times in C at all, regardless of how CTIME is specified. System V uses $TZ to get timezone information, so each user can have their own timezone. (one point for sysV) But there doesn't seem to be anyway to get other than USA style daylight savings time unless you have source and can hack ctime.c, where the daylight time stuff is hardcoded in. (minus 'n' points for sysV unless you live in the US) 4.2 has provisions for different types of daylight savings time, which can be changed via settimeofday(2). (The tables for european daylight time are wrong, but better than nothing) 4.3 fixes (I think) the tables for europe, and adds one for Canada, which was different than the US in '74 and '75. (Like, who cares *now* ?) I've modified date(1) for Utek 2.2, adding -z and -d options, to set the timezone and type of daylight savings time. I'm thinking about teaching localtime(3) about $TZ, so that you could type: "TZ=some_other_zone date" and get the time for some other timezone easily. (e.g. to see if it's a good time to call someone.) comments? > The ANSI standard is specifying that >a library function be able to produce a value that is not available on >a large number of systems. ... The only time >function supplied by the operating system effectively returns the value on >the wall clock beside the operator's console. There is no available hint >about the relation between this, and GMT or whether it is daylight >savings time or not. > ... > I can live with the GETENV description since nothing stops me from >just defining a GETENV that always returns NULL. I can't really live >with the requirement that I supply routines LOCALTIME, and GMTIME >since both require me to return information that is not available to me. Let's be careful before we start throwing things away just because some other system can't support it. We can't make C fit the lowest common denominator, because that's pretty low. Throw away time functions because the Fubar 2000 running SNAFUDOS can't support them, and throw away floating point because the Whatiz 907 can't support it, and throw away upper/lower case because... (you get the idea) Snoopy (ECS Ronin #901) tektronix!tekecs!doghouse.TEK!snoopy
henry@utzoo.UUCP (Henry Spencer) (11/23/85)
> And then they define a function gmtime(const time_t *timer) that takes > a pointer to the arithmetic value, which it is not going to change anyway. > Why not just take the value itself instead of the pointer? *That* one, at least, is easy to explain: because that is the way the Unix function does it, for historical reasons, and nobody wants to break all that working code. As for why the Unix function does it that way... gmtime() predates the arrival of "long" in C. Back In The Bad Old Days, with no type "long", 32-bit values had to be manipulated as small arrays of int. There were functions to add them, etc. Note that one can pass the address of an array but not the array itself. And that's why virtually all Unix library functions that deal with time take pointers to time_t rather than just time_t. (If you want a really odd example, look at the time(2) manual page -- it has two different ways to return its value!) Oh yes, a word to the careless (and to Laura for her book): one should not assume that time_t and long are the same type. Sometimes they're not, old (e.g. V7) or broken (e.g. 4.2BSD) manuals notwithstanding. -- Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry
ron@brl-sem.ARPA (Ron Natalie <ron>) (11/23/85)
> The standard obviously didn't put much thought into anything related to > times. They define type "time_t" as an arithmetic type that represents > the time, and then define a difftime(time_t time1,time_t time2) that > computes the difference between these two arithmetic values. Why the > function? Does the standard have a new arithmetic type on which the > operation of subtraction is not allowed? Because this isn't ADA. Well if the specification says arithmatic type, I'll take exception with it. Time_t on many systems is a struct. Even so, consider a machine that stores the time packed in a an int or other arithmatic type that is not just some count of ticks since some base time. We had one system that encoded it's time in BCD (stupid military system required it), obviously you just can't subtract two BCD numbers that are stored in an int and expect it to do something meaningful. -Ron
meissner@rtp47.UUCP (Michael Meissner) (11/24/85)
In article <171@watmath.UUCP> rbutterworth@watmath.UUCP (Ray Butterworth) writes > >The standard obviously didn't put much thought into anything related to >times. They define type "time_t" as an arithmetic type that represents >the time, and then define a difftime(time_t time1,time_t time2) that >computes the difference between these two arithmetic values. Why the >function? Does the standard have a new arithmetic type on which the >operation of subtraction is not allowed? >And then they define a function gmtime(const time_t *timer) that takes >a pointer to the arithmetic value, which it is not going to change anyway. >Why not just take the value itself instead of the pointer? > As a member of the ANSI X3J11 committee, let me point out what I saw as the reasoning behind this. First of all, there was great controversy as to whether the time routines should be standerized or not. Personally, I was against them (some systems don't have clocks, there are systems that don't know the difference between GMT and localtime, and what do we do with a system in a plane or space shuttle). As regards to gmtime, it has to be a pointer because that's the way UNIX does it. Historically, this is because the original PDP-11 V6 UNIX (and earlier) did not have the long data type, and time_t was defined as an array of two integers. The rational behind difftime is that the implementor does not necessarily have to store the number of seconds since Jan. 1, 1970. Rather the time field could be an arbitrary encoding, and difftime would allow the user to compare two times portabily (ie, write a make utility). As an example of an encoding, Data General's time field consists of 2 short integers fit into 1 long integer. The first is the number of days since Jan. 1, 1968, and the second is the number of biseconds since midnight. My C implementation actually uses the UNIX encoding for ctime/gmtime/localtime, and provides a separate dg_ctime/ dg_localtime, but could conceivably use the native encoding. Michael Meissner Data General ...{ ihnp4, decvax }!mcnc!rti-sel!rtp47!meissner
peter@graffiti.UUCP (Peter da Silva) (11/24/85)
> Several members of the X3J11 Committee are working on a rationale > document that will, I hope, clarify some apparently obscure choices. > It happens that a great deal of thought went into every aspect of > this issue. Yes, they took the entry for ctime from the third section of the UNIX manual and copied it verbatim. An enourmous amount of thought must have gone into this decision, and into the decision to pull floating point libraries in where they're not wanted by making difftime return a float. >> (paraphrased) why is the argument to *ctime a pointer to time_t? The reason for the pointer is a historical dreg dating back to early Version 6 'C' compilers that couldn't pass long integers to routines. -- Name: Peter da Silva Graphic: `-_-' UUCP: ...!shell!{graffiti,baylor}!peter IAEF: ...!kitty!baylor!peter
tim@ISM780B.UUCP (11/26/85)
> times. They define type "time_t" as an arithmetic type that > represents the time, and then define a difftime(time_t > time1,time_t time2) that computes the difference between these > two arithmetic values. Why the function? Does the standard have > a new arithmetic type on which the operation of subtraction is > not allowed? The difftime function first transforms both times to the frame of an observer at Greenwich (sp?). It needs to be a function, because the standard C subtraction operator knows nothing about general relativity. Tim Smith ihnp4!cithep!tim ima!ism780!tim
mikeb@inset.UUCP (Mike Banahan) (11/26/85)
In article <171@watmath.UUCP> rbutterworth@watmath.UUCP (Ray Butterworth) writes: >The standard obviously didn't put much thought into anything related to >times. They define type "time_t" as an arithmetic type that represents >the time, and then define a difftime(time_t time1,time_t time2) that >computes the difference between these two arithmetic values. Why the >function? Does the standard have a new arithmetic type on which the >operation of subtraction is not allowed? >And then they define a function gmtime(const time_t *timer) that takes >a pointer to the arithmetic value, which it is not going to change anyway. >Why not just take the value itself instead of the pointer? Because they realised that some systems store time in microseconds, others in encoded formats with seconds in the bottom 6 bits, hours in the next 5, etc ad nauseam. The data type may be arithmetic, but its contents aren't guaranteed to be in any given format. Hence the procedural interfaces. Perhaps they put more thought into it than you did? -- Mike Banahan, Technical Director, The Instruction Set Ltd. mcvax!ukc!inset!mikeb
atbowler@watmath.UUCP (Alan T. Bowler [SDG]) (11/27/85)
In article <628@sftig.UUCP> lr@sftig.UUCP (L.Rosler) writes: >Perhaps it is unrealistic to expect people who state what the "ANSI >standard is specifying" to have read it. The draft actually says, >"The gmtime function returns ... a null pointer if GMT is not available." >The presumption is that if the time() function works at all (see my >previous posting on THAT subject), then it is reasonable to expect >localtime() to work also. If gmtime() is available, it must work >as specified; otherwise it fails in a specified way. In other words, >"If you are going to supply gmtime functionality, do it like this...". Ooops, I missed the line about GMTIME returning a NULL. Thank you for pointing it out. (Now, hopefully having extracted my foot from my mouth (-: ) LOCALTIME, however, is still expected to return a flag saying wheither or not daylight savings time is in effect. Does, "The local time zone and Daylight Savings Time are implementation defined." mean that I can redefine what the term "Daylight Savings Time" means and always set the value zero? This seems like a no win situation. On related problem, even assuming I have access to a daylight savings flag, LOCALTIME, is supposed to return the daylight savings flag for some arbitrary time_t value it is given. Is this supposed to be today's flag, or the value it would have had on the date being referenced? As has been discussed before there is no algorithm that will predict when daylight time is in effect since it is in many places under control of local politicians. Is there some reading of the standard, or some more lines that can be added telling me what to implement on a machine which has no access to a daylight savings time flag.