Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #75804 > unrolled thread
| Started by | G G <gdotone@gmail.com> |
|---|---|
| First post | 2015-11-11 22:55 -0800 |
| Last post | 2015-11-12 16:57 -0800 |
| Articles | 13 on this page of 33 — 11 participants |
Back to article view | Back to comp.lang.c
double strtod( const char *nPtr, char **endPrt); G G <gdotone@gmail.com> - 2015-11-11 22:55 -0800
Re: double strtod( const char *nPtr, char **endPrt); Richard Heathfield <rjh@cpax.org.uk> - 2015-11-12 07:24 +0000
Re: double strtod( const char *nPtr, char **endPrt); G G <gdotone@gmail.com> - 2015-11-11 23:42 -0800
Re: double strtod( const char *nPtr, char **endPrt); Keith Thompson <kst-u@mib.org> - 2015-11-12 08:31 -0800
Re: double strtod( const char *nPtr, char **endPrt); supercat@casperkitty.com - 2015-11-12 08:52 -0800
Re: double strtod( const char *nPtr, char **endPrt); G G <gdotone@gmail.com> - 2015-11-12 09:43 -0800
Re: double strtod( const char *nPtr, char **endPrt); Richard Heathfield <rjh@cpax.org.uk> - 2015-11-12 17:59 +0000
Re: double strtod( const char *nPtr, char **endPrt); Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-11-12 13:10 -0500
Re: double strtod( const char *nPtr, char **endPrt); James Kuyper <jameskuyper@verizon.net> - 2015-11-12 13:19 -0500
Re: double strtod( const char *nPtr, char **endPrt); Keith Thompson <kst-u@mib.org> - 2015-11-12 11:32 -0800
Re: double strtod( const char *nPtr, char **endPrt); supercat@casperkitty.com - 2015-11-12 12:17 -0800
Re: double strtod( const char *nPtr, char **endPrt); Keith Thompson <kst-u@mib.org> - 2015-11-12 12:48 -0800
Re: double strtod( const char *nPtr, char **endPrt); supercat@casperkitty.com - 2015-11-12 13:39 -0800
Re: double strtod( const char *nPtr, char **endPrt); glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-11-12 23:24 +0000
Re: double strtod( const char *nPtr, char **endPrt); Keith Thompson <kst-u@mib.org> - 2015-11-12 17:14 -0800
Re: double strtod( const char *nPtr, char **endPrt); supercat@casperkitty.com - 2015-11-12 17:42 -0800
Re: double strtod( const char *nPtr, char **endPrt); Keith Thompson <kst-u@mib.org> - 2015-11-12 18:20 -0800
Re: double strtod( const char *nPtr, char **endPrt); glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-11-12 23:15 +0000
Re: double strtod( const char *nPtr, char **endPrt); Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-11-12 18:30 -0500
Re: double strtod( const char *nPtr, char **endPrt); supercat@casperkitty.com - 2015-11-12 16:47 -0800
Re: double strtod( const char *nPtr, char **endPrt); Keith Thompson <kst-u@mib.org> - 2015-11-12 18:07 -0800
Re: double strtod( const char *nPtr, char **endPrt); glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-11-13 02:41 +0000
Re: double strtod( const char *nPtr, char **endPrt); glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-11-13 02:53 +0000
Re: double strtod( const char *nPtr, char **endPrt); G G <gdotone@gmail.com> - 2015-11-12 12:17 -0800
Re: double strtod( const char *nPtr, char **endPrt); Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-12 12:34 -0800
Re: double strtod( const char *nPtr, char **endPrt); Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-12 23:54 +0000
Re: double strtod( const char *nPtr, char **endPrt); Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-12 16:23 -0800
Re: double strtod( const char *nPtr, char **endPrt); Ian Collins <ian-news@hotmail.com> - 2015-11-13 14:09 +1300
Re: double strtod( const char *nPtr, char **endPrt); Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-12 17:31 -0800
Re: double strtod( const char *nPtr, char **endPrt); Ian Collins <ian-news@hotmail.com> - 2015-11-13 14:46 +1300
Re: double strtod( const char *nPtr, char **endPrt); Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-13 02:07 +0000
Re: double strtod( const char *nPtr, char **endPrt); David Brown <david.brown@hesbynett.no> - 2015-11-13 08:48 +0100
Re: double strtod( const char *nPtr, char **endPrt); Keith Thompson <kst-u@mib.org> - 2015-11-12 16:57 -0800
Page 2 of 2 — ← Prev page 1 [2]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-11-12 18:07 -0800 |
| Message-ID | <lna8qips8e.fsf@kst-u.example.com> |
| In reply to | #75893 |
Eric Sosman <esosman@comcast-dot-net.invalid> writes:
> On 11/12/2015 6:15 PM, glen herrmannsfeldt wrote:
>> Keith Thompson <kst-u@mib.org> wrote:
>>> supercat@casperkitty.com writes:
>> (snip)
>>>> While I don't think anything would forbid an implementation where string
>>>> literals could create objects at run time, I would suggest that they more
>>>> often create objects at compile time which are aggregated into an object
>>>> which gets created at load time. String literal expressions then identify
>>>> pieces of that object.
>>
>>> Objects don't exist at compile time.
>>
>> I suspect it isn't part of the C standard, but most systems create
>> static objects at compile time. They exist in the object module,
>> and resultant load module.
>
> I think Keith's point is that the contents of the "object module"
> and "load module" are not objects until run time; they're just
> instructions to the starter-upper to create some objects before
> calling main().
Exactly.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | glen herrmannsfeldt <gah@ugcs.caltech.edu> |
|---|---|
| Date | 2015-11-13 02:41 +0000 |
| Message-ID | <n23iju$17g$1@speranza.aioe.org> |
| In reply to | #75893 |
Eric Sosman <esosman@comcast-dot-net.invalid> wrote: (snip, Keith wrote) >>> Objects don't exist at compile time. (then I wrote) >> I suspect it isn't part of the C standard, but most systems create >> static objects at compile time. They exist in the object module, >> and resultant load module. > I think Keith's point is that the contents of the "object module" > and "load module" are not objects until run time; they're just > instructions to the starter-upper to create some objects before > calling main(). On most systems, though, they have actual addresses, though those addresses will sometime later be relocated. On systems with PC relative addressing, they don't need relocation. >>> A compiler doesn't create an object. It generates code that results in >>> the creation of an object when that code is executed. >> C conveniently makes it hard to create large static objects initialized >> to other than zero. Many object module and load module forms have >> optmizations for static zero, but not all. > ... which seems to support Keith's view. You write source code > for a big zero object like `static char array[10000];', but you may > search in vain for a 10000-byte thingumabob in the products of the > compiler and linker. Unix seems to have something special for zero. I think I remember when zero compression was added to the MS-DOS linker as a command line option. But the OS/360 linker doesn't do that. Early in my Fortran programming years (late OS/360 years) I found out about DATA statements, and once used one to zero an array. Easier than writing the loop to do it. Sometime later, I punched out the object program on cards. The program was pretty small, but many cards full of zeros still had to be punched. (Binary zero has five holes punched, so a lot of holes.) > There's a good chance you'll just find a little > notation somewhere that says "Dear run-time: Please set aside 42KB of > pre-zeroed bytes (maybe called bss), and I'll treat bytes X through > X+9999 of that region as `array'." If that sort of thing happens, it's > pretty clear that the object has not been created prior to run-time. It seems that unix special cases zero. Anything else seems to appear in the object program, even if repeated many times. It is probably faster to initialize with a loop than to read in all those values from disk. A compiler or linker could figure that out. Seems that some systems can execute gzipped files. In that case, the loader has to ungzip while reading from disk. That isn't so hard, and is likely done in software, but even so all the bytes are in memory before the first instruction related to C is executed. -- glen
[toc] | [prev] | [next] | [standalone]
| From | glen herrmannsfeldt <gah@ugcs.caltech.edu> |
|---|---|
| Date | 2015-11-13 02:53 +0000 |
| Message-ID | <n23jac$24m$1@speranza.aioe.org> |
| In reply to | #75893 |
Eric Sosman <esosman@comcast-dot-net.invalid> wrote: (snip, I wrote) >> I suspect it isn't part of the C standard, but most systems create >> static objects at compile time. They exist in the object module, >> and resultant load module. (snip) > ... which seems to support Keith's view. You write source code > for a big zero object like `static char array[10000];', but you may > search in vain for a 10000-byte thingumabob in the products of the > compiler and linker. There's a good chance you'll just find a little > notation somewhere that says "Dear run-time: Please set aside 42KB of > pre-zeroed bytes (maybe called bss), and I'll treat bytes X through > X+9999 of that region as `array'." If that sort of thing happens, it's > pretty clear that the object has not been created prior to run-time. This reminds me of a story from some years ago, when big computers could be run by a Z80. Someone I knew had a system from Zilog, a complete hardware and software setup as supplied by Zilog. They also, for a different project, had similar hardware, but that didn't have the Zilog OS. That is, not purchased as a hardware/software combination. Just to see what would happen, this person decided to put the Zilog floppy into the other system: when it starts up, out comes "Hardware error, call Zilog". A search through the files on the disk didn't find that message anywhere. The program creates the string in memory just before printing it, then removed it from memory. As I noted earlier, presumably a C program could create a string constant in memory just before it was needed, though it seems easier to just keep it around. To finish the story, the person found a different part number on the Zilog counter/timer chip and called Zilog about buying one. He was quoted a much higher price. It seems that there is a defective bit in early versions of the chip, and the Zilog OS tests for that defective bit. This wasn't with the goal of using the software on the other system, but just to understand why it wouldn't work. -- glen
[toc] | [prev] | [next] | [standalone]
| From | G G <gdotone@gmail.com> |
|---|---|
| Date | 2015-11-12 12:17 -0800 |
| Message-ID | <2e9ca419-ce5a-43af-acd4-86f9d312dd83@googlegroups.com> |
| In reply to | #75868 |
Keith, James, Eric, Richard, I'm going to get it. I just need to refer back to your discussions until I get it straight. Thanks everyone.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2015-11-12 12:34 -0800 |
| Message-ID | <31297c7a-2d50-43d7-bbcf-7bff154ebb46@googlegroups.com> |
| In reply to | #75804 |
On Thursday, November 12, 2015 at 6:55:52 AM UTC, G G wrote: > double strtod( const char *nPtr, char **endPrt ); > (and functions like it) > > nPtr is a pointer to a character constant > > endPtr is a pointer to a pointer to a character or > endPtr is a pointer to a pointer of type character? > > > nPtr is not changeable. i mean what nPtr points > to is not changeable. > > endPtr is a pointer which points to another to a character > that is allowed to change? > Consider this. char line[1024]; /* modifiable */ const char * end; double x; fgets(line, 1024, stdin); x = strtod(line, &end); /* we want to null terminate the numerical part of line */ if(end != line) *end = 0; /* we can't do that if end is a const char * */ It illustrates the problems with const. You could define strtod_const and strtod_variable, but the language ends up talking to itself.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-11-12 23:54 +0000 |
| Message-ID | <87h9kqzsc8.fsf@bsb.me.uk> |
| In reply to | #75876 |
Malcolm McLean <malcolm.mclean5@btinternet.com> writes: <snip> > Consider this. > > > char line[1024]; /* modifiable */ > const char * end; > double x; > > fgets(line, 1024, stdin); > x = strtod(line, &end); > /* we want to null terminate the numerical part of line */ > if(end != line) > *end = 0; > /* we can't do that if end is a const char * */ > > It illustrates the problems with const. What problem does it illustrate? -- that you've used the wrong type by adding const? Why is that a problem with const? (There are problems with const in C, but I don't see which one you are illustrating here.) <snip> -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2015-11-12 16:23 -0800 |
| Message-ID | <0d5dd3cf-f3bf-4e1e-a61e-d7e8df92453d@googlegroups.com> |
| In reply to | #75894 |
On Thursday, November 12, 2015 at 11:55:02 PM UTC, Ben Bacarisse wrote: > Malcolm McLean <malcolm.mclean5@btinternet.com> writes: > <snip> > > Consider this. > > > > > > char line[1024]; /* modifiable */ > > const char * end; > > double x; > > > > fgets(line, 1024, stdin); > > x = strtod(line, &end); > > /* we want to null terminate the numerical part of line */ > > if(end != line) > > *end = 0; > > /* we can't do that if end is a const char * */ > > > > It illustrates the problems with const. > > What problem does it illustrate? -- that you've used the wrong type by > adding const? Why is that a problem with const? (There are problems > with const in C, but I don't see which one you are illustrating here.) > strtod take a const char *, so the "end" pointer should also be a const pointer. Otherwise if you can defeat the const system by passing strtod a const string, and writing to the end pointer. (C++ can actually crash if you try to call an analagous function on the c_str() return from a const std::string. That happened to me today. I had to copy the string to a temporary. This is despite never writing to the pointer). But we can't declare the end pointer to be const qualified, because if we do that, you can't write through it, which you'll often legitimately want to do.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2015-11-13 14:09 +1300 |
| Message-ID | <dakrifFi0ttU3@mid.individual.net> |
| In reply to | #75897 |
Malcolm McLean wrote: > On Thursday, November 12, 2015 at 11:55:02 PM UTC, Ben Bacarisse wrote: >> Malcolm McLean <malcolm.mclean5@btinternet.com> writes: >> <snip> >>> Consider this. >>> >>> >>> char line[1024]; /* modifiable */ >>> const char * end; >>> double x; >>> >>> fgets(line, 1024, stdin); >>> x = strtod(line, &end); >>> /* we want to null terminate the numerical part of line */ >>> if(end != line) >>> *end = 0; >>> /* we can't do that if end is a const char * */ >>> >>> It illustrates the problems with const. >> >> What problem does it illustrate? -- that you've used the wrong type by >> adding const? Why is that a problem with const? (There are problems >> with const in C, but I don't see which one you are illustrating here.) >> > strtod take a const char *, so the "end" pointer should also > be a const pointer. Otherwise if you can defeat the const system > by passing strtod a const string, and writing to the end pointer. This is a well known flaw of the C standard library function, not of const. > (C++ can actually crash if you try to call an analagous function > on the c_str() return from a const std::string. That happened to > me today. I had to copy the string to a temporary. This is despite > never writing to the pointer). Which one? > But we can't declare the end pointer to be const qualified, because > if we do that, you can't write through it, which you'll often > legitimately want to do. In the case of C++, it would fail to compile. In the case of C, I would expect most compilers to emit a warning. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2015-11-12 17:31 -0800 |
| Message-ID | <181c6700-1622-491e-8f25-2cb24d4cc003@googlegroups.com> |
| In reply to | #75905 |
On Friday, November 13, 2015 at 1:09:51 AM UTC, Ian Collins wrote:
> Malcolm McLean wrote:
> > On Thursday, November 12, 2015 at 11:55:02 PM UTC, Ben Bacarisse wrote:
> >> Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
> >> <snip>
> >>> Consider this.
> >>>
> >>>
> >>> char line[1024]; /* modifiable */
> >>> const char * end;
> >>> double x;
> >>>
> >>> fgets(line, 1024, stdin);
> >>> x = strtod(line, &end);
> >>> /* we want to null terminate the numerical part of line */
> >>> if(end != line)
> >>> *end = 0;
> >>> /* we can't do that if end is a const char * */
> >>>
> >>> It illustrates the problems with const.
> >>
> >> What problem does it illustrate? -- that you've used the wrong type by
> >> adding const? Why is that a problem with const? (There are problems
> >> with const in C, but I don't see which one you are illustrating here.)
> >>
> > strtod take a const char *, so the "end" pointer should also
> > be a const pointer. Otherwise if you can defeat the const system
> > by passing strtod a const string, and writing to the end pointer.
>
> This is a well known flaw of the C standard library function, not of const.
>
> > (C++ can actually crash if you try to call an analagous function
> > on the c_str() return from a const std::string. That happened to
> > me today. I had to copy the string to a temporary. This is despite
> > never writing to the pointer).
>
> Which one?
>
The code was
JSONparser::JSONParser(const std::string &json);
std::string const &aClass::getData() { return mData;};
void myobject::foo(const aClass &aParam)
{
// data string has JSON attached to it
JSONParser jparser(strchr(aParam().getData().c_str(), '{'));
}
compiled nicely, but crashed out horribly.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2015-11-13 14:46 +1300 |
| Message-ID | <daktnaFi0ttU4@mid.individual.net> |
| In reply to | #75908 |
Malcolm McLean wrote:
> On Friday, November 13, 2015 at 1:09:51 AM UTC, Ian Collins wrote:
>> Malcolm McLean wrote:
>>
>>> (C++ can actually crash if you try to call an analagous function
>>> on the c_str() return from a const std::string. That happened to
>>> me today. I had to copy the string to a temporary. This is despite
>>> never writing to the pointer).
>>
>> Which one?
>>
> The code was
>
> JSONparser::JSONParser(const std::string &json);
>
> std::string const &aClass::getData() { return mData;};
>
> void myobject::foo(const aClass &aParam)
> {
> // data string has JSON attached to it
> JSONParser jparser(strchr(aParam().getData().c_str(), '{'));
Well strchr() is one of the functions where C++ provides the correct
overload, so your problem had nothing to do with const.
This type of crash usually occurs when the original string object goes
out of scope and the data pointer is invalid.
--
Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-11-13 02:07 +0000 |
| Message-ID | <87a8qizm6z.fsf@bsb.me.uk> |
| In reply to | #75897 |
Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
> On Thursday, November 12, 2015 at 11:55:02 PM UTC, Ben Bacarisse wrote:
>> Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
>> <snip>
>> > Consider this.
>> >
>> >
>> > char line[1024]; /* modifiable */
>> > const char * end;
>> > double x;
>> >
>> > fgets(line, 1024, stdin);
>> > x = strtod(line, &end);
>> > /* we want to null terminate the numerical part of line */
>> > if(end != line)
>> > *end = 0;
>> > /* we can't do that if end is a const char * */
>> >
>> > It illustrates the problems with const.
>>
>> What problem does it illustrate? -- that you've used the wrong type by
>> adding const? Why is that a problem with const? (There are problems
>> with const in C, but I don't see which one you are illustrating here.)
>>
> strtod take a const char *, so the "end" pointer should also
> be a const pointer. Otherwise if you can defeat the const system
> by passing strtod a const string, and writing to the end pointer.
Would that problem not be better illustrated by a program that does
exactly that? To the non-expert, your example just looks like a
misused const since that's the only thing wrong with the code.
<snip>
> But we can't declare the end pointer to be const qualified, because
> if we do that, you can't write through it, which you'll often
> legitimately want to do.
No, that would not a problem:
if (end != line)
line[end-line] = 0;
The problem is that you can "get round" const either accidentally or on
purpose using oddly-defined library functions. Your example didn't
illustrate that.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2015-11-13 08:48 +0100 |
| Message-ID | <n244gi$sqp$1@dont-email.me> |
| In reply to | #75897 |
On 13/11/15 01:23, Malcolm McLean wrote: > On Thursday, November 12, 2015 at 11:55:02 PM UTC, Ben Bacarisse wrote: >> Malcolm McLean <malcolm.mclean5@btinternet.com> writes: >> <snip> >>> Consider this. >>> >>> >>> char line[1024]; /* modifiable */ >>> const char * end; >>> double x; >>> >>> fgets(line, 1024, stdin); >>> x = strtod(line, &end); >>> /* we want to null terminate the numerical part of line */ >>> if(end != line) >>> *end = 0; >>> /* we can't do that if end is a const char * */ >>> >>> It illustrates the problems with const. >> >> What problem does it illustrate? -- that you've used the wrong type by >> adding const? Why is that a problem with const? (There are problems >> with const in C, but I don't see which one you are illustrating here.) >> > strtod take a const char *, so the "end" pointer should also > be a const pointer. Otherwise if you can defeat the const system > by passing strtod a const string, and writing to the end pointer. > > (C++ can actually crash if you try to call an analagous function > on the c_str() return from a const std::string. That happened to > me today. I had to copy the string to a temporary. This is despite > never writing to the pointer). > > But we can't declare the end pointer to be const qualified, because > if we do that, you can't write through it, which you'll often > legitimately want to do. > Just cast away the constness of "end": *(char*) end = 0; That is perfectly legal C. You can freely cast way "const" from a pointer when you know the thing you are point at is not const. Or access the array directly: line[end - line] = 0;
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-11-12 16:57 -0800 |
| Message-ID | <lntwoqpvga.fsf@kst-u.example.com> |
| In reply to | #75876 |
Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
> On Thursday, November 12, 2015 at 6:55:52 AM UTC, G G wrote:
>> double strtod( const char *nPtr, char **endPrt );
>> (and functions like it)
>>
>> nPtr is a pointer to a character constant
>>
>> endPtr is a pointer to a pointer to a character or
>> endPtr is a pointer to a pointer of type character?
>>
>>
>> nPtr is not changeable. i mean what nPtr points
>> to is not changeable.
>>
>> endPtr is a pointer which points to another to a character
>> that is allowed to change?
>>
> Consider this.
>
>
> char line[1024]; /* modifiable */
> const char * end;
> double x;
>
> fgets(line, 1024, stdin);
> x = strtod(line, &end);
> /* we want to null terminate the numerical part of line */
> if(end != line)
> *end = 0;
> /* we can't do that if end is a const char * */
>
> It illustrates the problems with const. You could define strtod_const
> and strtod_variable, but the language ends up talking to itself.
You shouldn't have the "const" on the declaration of "end".
It's true that strtod can give you a pointer to non-const that points
into a read-only string. Another illustration of this:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char *line = "1.23xyz";
char *end;
double x = strtod(line, &end);
// x == 1.23, end points to the 'x'
*end = '\0'; // kaboom
}
Several other functions, including strstr() and strchr(), have the same
problem.
(C++ has addressed this, at least in some cases, by providing
const-consistent overloaded versions.)
IMHO the best solution would have been to provide two different versions
of each of these functions, one for const data and one for non-const
data.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | comp.lang.c
csiph-web