karzes@mfci.UUCP (Tom Karzes) (07/20/88)
While on the subject of enums, here's something that's always bothered me.
If you define an enum with a long list of values, a natural thing to want
to do is determine the number of values in the enum (sort of like sizeof).
For example:
enum tree {
oak,
elm,
maple,
birch,
willow,
cypress,
spruce
};
Now I'd like to define TREE_COUNT to be the number of trees. So I have to
painfully count them, and write:
#define TREE_COUNT 7
and hope that people correctly update this macro every time they add or
delete a tree.
Sure, I suppose in this case I could write:
#define TREE_COUNT ((int) spruce + 1)
(This assumes that there aren't any trees which have been given explicit
values in the enum.) But this is still a pain to maintain, since you
have to fix the macro every time the last tree changes.
Of course, in the presence of enum members which are given explicit values
(which also introduces the possibility of duplicate values), you may want
to know something more than just the number of members (e.g., the number
of distinct values, the minimum and maximum values, etc.). However, for
most situations it would be sufficient to simply know the number of members
in the enum.
Does ANSI C provide a reasonable way to do this?
barmar@think.COM (Barry Margolin) (07/21/88)
In article <469@m3.mfci.UUCP> karzes@mfci.UUCP (Tom Karzes) writes: > enum tree { > oak, > elm, > maple, > birch, > willow, > cypress, > spruce > }; > >Now I'd like to define TREE_COUNT to be the number of trees. So I have to >painfully count them, and write: > > #define TREE_COUNT 7 How about enum tree { oak, elm, maple, birch, willow, cypress, spruce, TREE_COUNT /* must always be last */ } ? The only problem with this is if you're into strong typing; the count of trees isn't actually a kind of tree. But since you're programming in C we can assume that you aren't fanatical about such things. Barry Margolin Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
henry@utzoo.uucp (Henry Spencer) (07/23/88)
In article <469@m3.mfci.UUCP> karzes@mfci.UUCP (Tom Karzes) writes: >While on the subject of enums, here's something that's always bothered me. >If you define an enum with a long list of values, a natural thing to want >to do is determine the number of values in the enum... >Does ANSI C provide a reasonable way to do this? No. X3J11 C (it's not quite officially ANSI C yet) almost didn't include enums at all, since they are so obviously a crude patch onto the language. It does in fact include them, in the simplest and stupidest form possible. -- Anyone who buys Wisconsin cheese is| Henry Spencer at U of Toronto Zoology a traitor to mankind. --Pournelle |uunet!mnetor!utzoo! henry @zoo.toronto.edu
bright@Data-IO.COM (Walter Bright) (07/23/88)
In article <469@m3.mfci.UUCP> karzes@mfci.UUCP (Tom Karzes) writes:
<If you define an enum with a long list of values, a natural thing to want
<to do is determine the number of values in the enum (sort of like sizeof).
< enum tree {oak,elm,maple,birch,willow,cypress,spruce};
<Now I'd like to define TREE_COUNT to be the number of trees. So I have to
<painfully count them, and write:
< #define TREE_COUNT 7
<and hope that people correctly update this macro every time they add or
<delete a tree.
<Does ANSI C provide a reasonable way to do this?
I use:
enum tree {oak,elm,maple,birch,willow,cypress,spruce,TREE_COUNT};
nevin1@ihlpf.ATT.COM (00704a-Liber) (07/27/88)
In article <1988Jul22.171612.6225@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: >No. X3J11 C (it's not quite officially ANSI C yet) almost didn't include >enums at all, since they are so obviously a crude patch onto the language. >It does in fact include them, in the simplest and stupidest form possible. By saying that the dpANS C version of enums is 'the simplest and stupidest form possible', you have implied that there are much better forms of enums around. Could you please enlighten us on to what these might be? Thanks, -- _ __ NEVIN J. LIBER ..!att!ihlpf!nevin1 (312) 979-???? ' ) ) You are in a maze of twisty little / / _ , __o ____ email paths, all different. / (_</_\/ <__/ / <_ These are solely MY opinions, not AT&T's, blah blah blah
alex@cca.CCA.COM (Alexis Layton) (07/28/88)
To jump into this fray, I think I'd have to agree with Henry. Enums are completely superfluous if they do not provide both type-checking and better storage control. I would like to see enum have the following type-checking properties: convertible to and from ints automatically, but only assignable to enums of the same type. This is very much like the relationship between pointers and pointers to void. enum able { Alpha, Beta }; enum baker { Red, Green }; enum able a; enum baker b; int i; a = Alpha; /* ok */ b = Green; /* ok */ a = Green; /* oops: wrong type */ a = b; /* ditto */ a = 6; /* ok, ints convertible to enums */ i = a; /* ok, enums convertible to ints */ b = i; /* also ok */ i = Green; /* ok */ Actually, it may be better to restrict int->enum; so that "a = 6" above would fail without explicit cast. But enum->int must be allowed (which the pcc does not), so you can have char *baker_names[] = { "Red", "Green" }; and say printf("%s\n", enum_names[b]); A second useful thing with enums would be if the "short" and "long" adjectives would apply to them. (You'd also like a "char"-size one, but "char" is not an adjective; don't know just what to do about this, maybe "byte"?) Then you could easily specify smaller enumeration sizes without using bitfields. Well, it's probably too late now for the ANSII standard; but maybe on the next go-around (you know, NEXT year.... :-) ) this might be looked into. Alexis Layton alex@CCA.CCA.COM
bill@proxftl.UUCP (T. William Wells) (07/28/88)
3.5.2.2: "The identifiers in an enumerator list are declared as constants that have type _int_..." This says that each of the identifiers declared between the braces is an integer constant. Later in the same section: "Each enumerated type shall be compatible with an integer type; the choice of type is implementation-defined." An integer type is a char, all varieties of ints or longs, or an enumerated type (3.1.2.5). Thus the compiler writer is at liberty to store something declared as an enum in whatever size memory is appropriate, and to sign-extend or not as he sees fit. This seems to be a slight bug in the standard, as enumeration types are not required to be able to store the enumeration constants associated with it, nor to sign extend a short negative integer stored in an unsigned char.
gwyn@brl-smoke.ARPA (Doug Gwyn ) (07/29/88)
In article <31416@cca.CCA.COM> alex@CCA.CCA.COM (Alexis Layton) writes: >To jump into this fray, I think I'd have to agree with Henry. Enums are >completely superfluous if they do not provide both type-checking and better >storage control. No; they can materially aid in debugging. This was impressed on me earlier this week when I ran "dmdebug" in my terminal to track down an obsucre problem I was having with "sam"'s terminal part. Rob had written "sam" using enums where most of us would have used #defined manifest constant symbols. Because this tied a name to the numeric value, the debugger was able to show the symbolic names of the constants. That was very helpful..
orr@cs.glasgow.ac.uk (Fraser Orr) (07/29/88)
In article <31416@cca.CCA.COM> alex@CCA.CCA.COM (Alexis Layton) writes: > >Actually, it may be better to restrict int->enum; so that "a = 6" above >would fail without explicit cast. I agree. In fact, if you have any pretentions to having a reasonable type system, then this MUST be the case. >would fail without explicit cast. But enum->int must be allowed (which >the pcc does not), so you can have > > char *baker_names[] = { "Red", "Green" }; > >and say > > printf("%s\n", enum_names[b]); > Alternatively, you could have a decleration syntax, that allowed this: char * baker_names [ enum baker ] = {"Red", "Green" } ; and then printf("%s\n", baker_names[b]); /* Legal */ printf("%s\n", baker_names[i]); /* Illegal */ printf("%s\n", baker_names[a]); /* Illegal */ would be completely type secure, and the purpose of baker_names would be much more apparent to the reader. A previous poster ( sorry I've lost the article) asked how you could find the number of elements in an enum. Can anyone tellme why such information would be useful (appart from in array size declerations)? ==Fraser Orr ( Dept C.S., Univ. Glasgow, Glasgow, G12 8QQ, UK) UseNet: {uk}!cs.glasgow.ac.uk!orr JANET: orr@uk.ac.glasgow.cs ARPANet(preferred xAtlantic): orr%cs.glasgow.ac.uk@nss.cs.ucl.ac.uk
pardo@june.cs.washington.edu (David Keppel) (07/30/88)
When you have an enum of the form: enum light_t { ON, OFF, FIZZLING }; it can be nice to be able to print the members. I've written a (completely gross hack) program that scans a .c or .h and produces a file with an extra .c tacked on the end (e.g., .c.c or .h.c) that contains static initializers like: char *light_t_s[] = { "ON", "OFF", "FIZZLING", 0 }; On newer compilers you can then get a printable string by saying something like: for( light=ON; light <= FIZZLING; ++light ){ printf( "light is %s..\n", light_t_s[light] ); } Unfortunately this won't work when you have particular values assigned to an enumerted type ( FOO=-1, BAR=0, BORK=1 ). If you're on the DARPA net you can anonymous ftp from % ftp june.cs.washington.edu login: anonymous passwd: <your user name goes here> cd pub get enum.c Otherwise, send me e-mail and I'll send you a copy. There's no man page, and the code isn't of sufficient quality to post. Please keep me informed of changes... ;-D on ( A tool for all ages ) Pardo pardo@cs.washington.edu {rutgers,cornell,ucsd,ubc-cs,tektronix}!uw-beaver!june!pardo
davidsen@steinmetz.ge.com (William E. Davidsen Jr) (07/30/88)
A comment on the emum stuff lately... In article <5447@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704a-Liber,N.J.) writes: | In article <1988Jul22.171612.6225@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: | >No. X3J11 C (it's not quite officially ANSI C yet) almost didn't include | >enums at all, since they are so obviously a crude patch onto the language. | >It does in fact include them, in the simplest and stupidest form possible. Right on! enums were added because someone's preprocessor ran out of symbols. Then a good version of enum couldn't be added because of "prior atr." | | By saying that the dpANS C version of enums is 'the simplest and stupidest | form possible', you have implied that there are much better forms of enums | around. Could you please enlighten us on to what these might be? Here are my ideas on how an enum should work. Obviously no one gave me definitive insight, so consider this as opinion from someone who's been using computers for a while. If it looks a lot like Pascal, perhaps that portion of the language is more useful than the bulk of it. - enums should be a sequence of values in increasing order. The values should start at zero and increase by one. This allows the ++ and -- operators to be used in a meaningful way. - enums should not be conceptually mixed with ints. An explicit operation should be required to extract the ordinal value of an enum, and to set an enum to a value. - it would be nice to have separate namespace for the various enum types. The current implementation treats enum names as if they were #defined values. This was a good idea for structs, and it's a good idea here. It allows development of modules wothout having to have a master control for enum names. Statements like x=red would specify the "red" for the enum type of x. enum type conversion could require a cast. My feeling is that the enum type is not quite abstract enough to justify having another construct in the language. -- bill davidsen (wedu@ge-crd.arpa) {uunet | philabs | seismo}!steinmetz!crdos1!davidsen "Stupidity, like virtue, is its own reward" -me
henry@utzoo.uucp (Henry Spencer) (07/30/88)
In article <5447@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704a-Liber,N.J.) writes: >In article <1988Jul22.171612.6225@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: >>It does in fact include them, in the simplest and stupidest form possible. > >By saying that the dpANS C version of enums is 'the simplest and stupidest >form possible', you have implied that there are much better forms of enums >around. Could you please enlighten us on to what these might be? Well, I actually meant "stupidest" in the sense of "they didn't try to be clever about it", rather than "I disapprove of what they came up with". The fact is that enums have always occupied a vague never-never land between being a fancy way to declare integer constants and being something akin to Pascal's scalar types. The latter opens up a number of thorny questions like "can you use enums as array subscripts?". X3J11 decided -- in my opinion, wisely -- not to try to solve these problems. They also decided that enums were in sufficiently common use that deleting them entirely is not practical. So they opted to make them a way to declare integer constants and (sort of) integer subtypes. This sacrifices the error checking possible with more Pascalish semantics, but gets clear, simple, consistent semantics (definitely lacking for enums before) without adding unproven inventions to the language. -- MSDOS is not dead, it just | Henry Spencer at U of Toronto Zoology smells that way. | uunet!mnetor!utzoo!henry henry@zoo.toronto.edu
blandy@marduk.cs.cornell.edu (Jim Blandy) (07/30/88)
In article <11686@steinmetz.ge.com> davidsen@crdos1.UUCP (bill davidsen) writes: >Here are my ideas on how an enum should work... ... >- it would be nice to have separate namespace for the various enum > types. The current implementation treats enum names as if they were > #defined values. This was a good idea for structs, and it's a good > idea here. It allows development of modules wothout having to have a > master control for enum names. Statements like x=red would specify the > "red" for the enum type of x. enum type conversion could require a > cast. Although I agree with the principle, I think there might be some very difficult problems implementing a type checker to deal with this. It's more than just storing the definitions separately (as is done with members); enum constants don't have any special syntactic context (members have . and ->) to say "I'm an enum constant of such-and-such enum." In most C compilers (all the ones I know about, in any case), type checking is done from the bottom up; after you create the parse tree, you type the leaves, and work your way up. Since the type of an expression depends completely on its subexpressions, you can be sure you have the information by the time you need it. In order to separate constants of different enum types, you'd need a more powerful approach. You'd need to use some kind of 'type anticipation' system; in the fragment enum { uhlrich, zwingli } gar; enum { zwingli, uhlrich } bage; bage = zwingli; we need to be expecting one of the enums in particular before we can decide on the type of zwingli; we need to carry the type over the assignment operator. Even worse, consider f(zwingli); where f isn't prototyped... This can't be unraveled without a cast. Please note that structure and union members are not the same issue; there's never any need to consider the 'member' in a "struct.member" expression until you've found the type of the 'struct' . The member could never be anything complicated requiring further analysis, unlike the right operand of =. And how should we write our enum->int converter? A cast? What is (int) zwingli; ? We'd need a whole new syntax, another sizeof() - style thing: enumvalue(enumtag, enumconst) and enumvalue(enumvar, enumconst) (for untagged enums) It's not undoable, it's just more of a pain than you might think. > My feeling is that the enum type is not quite abstract enough to >justify having another construct in the language. As mentioned before, they're handy with a symbolic debugger, but I'll admit that that's not the best justification for a language feature. -- Jim Blandy - blandy@crnlcs.bitnet "And now," cried Max, "let the wild rumpus start!"
swarbric@tramp.Colorado.EDU (Frank Swarbrick) (07/31/88)
In article <11686@steinmetz.ge.com> davidsen@crdos1.UUCP (bill davidsen) writes: >Here are my ideas on how an enum should work. Obviously no one gave me >definitive insight, so consider this as opinion from someone who's been >using computers for a while. If it looks a lot like Pascal, perhaps >that portion of the language is more useful than the bulk of it. > >- enums should be a sequence of values in increasing order. The values > should start at zero and increase by one. This allows the ++ and -- > operators to be used in a meaningful way. Personally, I would like it to be even a little more like Pascal. Let's say I have typedef enum {red, white, blue} flag_colors; I would like: { flag_colors flag; flag = blue; flag++; } to have it so flag is now red. This is like Pascal's succ() and pred() operators. Frank Swarbrick (and, yes, the net.cat) swarbric@tramp.Colorado.EDU ...!{ncar|nbires}!boulder!tramp!swarbric "You shouldn't kill your brother -- except if he doesn't know what's right. If he can't love your heaven, ahh, it's a mercy for him to die." --Accept
sarima@gryphon.CTS.COM (Stan Friesen) (08/01/88)
In article <11686@steinmetz.ge.com> davidsen@crdos1.UUCP (bill davidsen) writes: > >- enums should be a sequence of values in increasing order. The values > should start at zero and increase by one. This allows the ++ and -- > operators to be used in a meaningful way. Yes, at least if I can force deviation from this order if necessary, such as making an enum to deasl with hardware generated values. > >- enums should not be conceptually mixed with ints. An explicit operation > should be required to extract the ordinal value of an enum, and to set > an enum to a value. Well, ONLY if you also redefine the syntax of the switch and case statements to allow both ints and enums. If I cannot do a switch on an enum where the case's have the enum constants as values an enum is almost useless. (After all I doubt that "case (int)red" is legal even if I would be willing to write such garbage). This is IMPORTANT. At least the ANSI draft requirement that enums act like int's also gaurentees that switch/case usage is legal and intuitive. > >- it would be nice to have separate namespace for the various enum > types. The current implementation treats enum names as if they were > #defined values. This was a good idea for structs, and it's a good > idea here. It allows development of modules wothout having to have a > master control for enum names. Statements like x=red would specify the > "red" for the enum type of x. enum type conversion could require a > cast. Very nice, I agree with my whole being. -- Sarima Cardolandion sarima@gryphon.CTS.COM aka Stanley Friesen rutgers!marque!gryphon!sarima Sherman Oaks, CA
karl@haddock.ISC.COM (Karl Heuer) (08/02/88)
In <2404@boulder.Colorado.EDU> swarbric@tramp (Frank Swarbrick) writes: >In <11686@steinmetz.ge.com> davidsen@crdos1.UUCP (bill davidsen) writes: >>[enums should be in sequence, so ++ and -- can be used meaningfully] > >Personally, I would like it to be even a little more like Pascal. [++ on the >last item should wrap to the first.] This is like Pascal's succ() and pred() I rather doubt that this is true of Pascal -- I've never heard of it before -- but I don't claim to be a Pascal expert, and anyway it doesn't affect my reply. I *don't* think it should be true of C, because it violates the principle of keeping the primitives simple. Most applications don't need the wraparound behavior, and it does have a nontrivial cost, therefore the ++ operator should simply step by one (with undefined behavior if you step off the end). Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
karl@haddock.ISC.COM (Karl Heuer) (08/02/88)
In article <19795@cornell.UUCP> blandy@cs.cornell.edu (Jim Blandy) writes: >And how should we write our enum->int converter? A cast? [Not enough >information if we want to allow duplication of enum names] Actually, I'd rather have enum arithmetic behave somewhat like pointers, in that enum+int => enum and enum-enum => int. Then you can convert an enum to its ordinal via an expression like "ord = RED - ZEROCOLOR;". This still doesn't solve the problem of duplication of enum names, but that's related to the sticky issue of anonymous aggregate constants. Using my proposed "remote" operator, you would write "remote(enum color, RED)" if RED alone is ambiguous. (Personally, I don't think it's worth the effort, but if "remote" or equivalent is added for other reasons, then it could probably handle this problem as well.) Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
ok@quintus.uucp (Richard A. O'Keefe) (08/02/88)
In article <2404@boulder.Colorado.EDU> swarbric@tramp.Colorado.EDU (Frank Swarbrick) writes: :Personally, I would like it to be even a little more like Pascal. :Let's say I have : typedef enum {red, white, blue} flag_colors; :I would like: : flag_colors flag; : flag = blue; : flag++; :to have it so flag is now red. :This is like Pascal's succ() and pred() operators. No it isn't. The Pascal fragment var: flag: (red, white, blue); ... flag := blue; flag := succ(blue); is *illegal* and any half-way decent Pascal system will give you a run-time error if you try it. (It's just the same in Ada.)
swarbric@tramp.Colorado.EDU (Frank Swarbrick) (08/02/88)
In article <5696@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes: }In <2404@boulder.Colorado.EDU> swarbric@tramp (Frank Swarbrick) writes: }>Personally, I would like it to be even a little more like Pascal. [++ on the }>last item should wrap to the first.] This is like Pascal's succ() and pred() } }I rather doubt that this is true of Pascal -- I've never heard of it before -- }but I don't claim to be a Pascal expert, and anyway it doesn't affect my }reply. I *don't* think it should be true of C, because it violates the }principle of keeping the primitives simple. Most applications don't need the }wraparound behavior, and it does have a nontrivial cost, therefore the ++ }operator should simply step by one (with undefined behavior if you step off }the end). Hmm, you seem to be correct that Pascal does not do this, either. I could have sworn that I had used it before, but I just tried it and it does not work. Oh well, now I feel really silly... Frank Swarbrick (and, yes, the net.cat) swarbric@tramp.Colorado.EDU ...!{ncar|nbires}!boulder!tramp!swarbric "You shouldn't kill your brother -- except if he doesn't know what's right. If he can't love your heaven, ahh, it's a mercy for him to die." --Accept
drc@claris.UUCP (Dennis Cohen) (08/02/88)
In article <5696@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes: >In <2404@boulder.Colorado.EDU> swarbric@tramp (Frank Swarbrick) writes: >>In <11686@steinmetz.ge.com> davidsen@crdos1.UUCP (bill davidsen) writes: >>>[enums should be in sequence, so ++ and -- can be used meaningfully] >> >>Personally, I would like it to be even a little more like Pascal. [++ on the >>last item should wrap to the first.] This is like Pascal's succ() and pred() > >I rather doubt that this is true of Pascal -- I've never heard of it before -- It's not true of Pascal. Both J&W and the ANSI/ISO standards explicitly state that SUCC on the last element and PRED on the first element of an enumeration are undefined and should produce an error condition. Dennis Cohen Claris Corp. ------------ Disclaimer: Any opinions expressed above are _MINE_!
firth@sei.cmu.edu (Robert Firth) (08/02/88)
In article <218@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes: >:This [wraparound of increment and decrement] >: is like Pascal's succ() and pred() operators. >No it isn't. The Pascal fragment > var: flag: (red, white, blue); > ... > flag := blue; > flag := succ(blue); >is *illegal* and any half-way decent Pascal system will give you a >run-time error if you try it. (It's just the same in Ada.) Quite true. Moreover, any compiler more than half decent will give you a COMPILE TIME warning; the Ada compiler I currently use gives WARNING: assignment must raise RANGE_ERROR which is very helpful. (Note that it can't be an error, since the code could be unreachable.)
bill@zycor.UUCP (bill) (08/05/88)
}In <2404@boulder.Colorado.EDU> swarbric@tramp (Frank Swarbrick) writes: }>In <11686@steinmetz.ge.com> davidsen@crdos1.UUCP (bill davidsen) writes: }>>[enums should be in sequence, so ++ and -- can be used meaningfully] }> }>Personally, I would like it to be even a little more like Pascal. [++ on the }>last item should wrap to the first.] This is like Pascal's succ() and pred() } }I rather doubt that this is true of Pascal -- I've never heard of it before -- In pascal, doing a succ() on the last item in an enum is a runtime error. In pascal, doing a pred() on the first item ... If your's wraps, it's broken. (Or maybe it's from Borland :-) )
dave@cs.arizona.edu (Dave P. Schaumann) (01/19/91)
In article <1991Jan17.211524.22679@nntp-server.caltech.edu> manning@nntp-server.caltech.edu (Evan Marshall Manning) writes: |dave@cs.arizona.edu (Dave P. Schaumann) writes: | ||Is there really that many C compilers out there that don't have 'enum'? | |Yes. Or have them wrong. | ||I have heard arguments against using enum which go "it wasn't there when I ||started using C". I trust such people do not use other advanced features of ||modern life, such as touch-tone phones, color TV, and the like. | |I started using C 4 years ago on a Sun & we had & used enums. In my current |project I started out using enums early & often. The documentation of the |target compiler claimed that enum was supported. On first compile under |PDOS I found that the compiler would forget about some enumerated constants |after the end of the first function in a given file. Out went the enums. | |Of course there will be an ANSI compiler for PDOS Real Soon Now.... I have difficulty in developing a code style based on broken compilers. There is another post on this thread which claims (paraphrased) "enums are difficult to implement correctly". I would think it would be just the opposite -- all they are is global symbolic constants. If I came across a compiler that didn't do enums right, I'd wonder what else they got wrong. I certainly wouldn't use the -O (optimize) flag -- except maybe for a few laughs. Hopefully, with the ever-spreading availability of gcc, such issues will soon be of historical interest only. ||For my part, I believe that 'enum' is a powerful addition to C, and now it is ||part of the standard. I use it unhesitatingly. | |Do use it, but not unhesitatingly. Hacking around a compiler with broken enums should be the exception to coding style, not the rule. |Your eyes are weary from staring at the CRT for so | Evan M. Manning |long. You feel sleepy. Notice how restful it is | is |to watch the cursor blink. Close your eyes. The |manning@gap.cco.caltech.edu |opinions stated above are yours. You cannot | manning@mars.jpl.nasa.gov |imagine why you ever felt otherwise. | gleeper@tybalt.caltech.edu Dave Schaumann | And then -- what then? Then, future... dave@cs.arizona.edu | -Weather Report