iiitsh@cybaswan.UUCP (Steve Hosgood) (08/03/89)
I am of the opinion that the historical reason for returning -1 for errors came from the fact that a lot of code can then be written: if ((foo = bar()) < 0) { <error code here> } ..which will compile neatly on most machines since all you do is test the 'N' flag (or whatever) which is usually present in architectures, and can be tested quickly. I notice that assembler programmers often return error status by setting the carry-bit however, this lets them still return an error value *and* flag the fact that an error has occurred all in one go. There is no prior art, but I've often wished for a way to do this in 'C'. Consider the advantages: The error return is unambiguous. The actual value that *does* get returned can be treated specially once it is known that an error occurred. The 'errno' system could probably be scrapped (I never liked it much anyway). Trouble is - how to you express a test of the carry-bit? Really it will need a syntactical addition to the language to be neat, and that is unlikely to be acceptable. I guess that an extension of the form: if (errval(foo = bar())) { <error code goes here> <could use 'foo' to get more details of the error> } ..would be most acceptable. 'errval' could be made a reserved word on new systems (tests the carry bit), and implemented as a macro on older ones for backward compatability: # define errval(x) (x) < 0 ..or # define errval(x) (x) == -1 ..or something like that, though some sort of cast will be reqd of course. Just an idea. Please contribute *arguments* for or against, not flames. Steve -----------------------------------------------+------------------------------ Steve Hosgood BSc, | Phone (+44) 792 295213 Image Processing and Systems Engineer, | Fax (+44) 792 295532 Institute for Industrial Information Techology,| Telex 48149 Innovation Centre, University of Wales, +------+ JANET: iiit-sh@uk.ac.swan.pyr Swansea SA2 8PP | UUCP: ..!ukc!cybaswan.UUCP!iiit-sh ----------------------------------------+------------------------------------- My views are not necessarily those of my employers!
pardo@june.cs.washington.edu (David Keppel) (08/05/89)
iiitsh@cybaswan.UUCP (Steve Hosgood) writes: >[errval(foo())] Until it is `prior art', it probably doesn't belong in dpANS C. Often, `-1' is used as a return value for things that can be array indicies, because `-1' can't be an array index. Having `errval' requires that you know not just the return type, but also which kinds of values are going to be meaningful (since, e.g., not all compilers have condition codes). To do this `right', you need a stronger typing system than C provides. ;-D on ( Stronger types, with 40% more resolving power! ) Pardo -- pardo@cs.washington.edu {rutgers,cornell,ucsd,ubc-cs,tektronix}!uw-beaver!june!pardo
siebren@piring.cwi.nl (Siebren van der Zee) (08/05/89)
iiitsh@cybaswan.UUCP (Steve Hosgood) writes: >[errval(foo())] Ok, and now the hard part: what should the code from the CALLED function look like? Siebren van der Zee, siebren@cwi.nl
mwm@eris.berkeley.edu (Mike (I'll think of something yet) Meyer) (08/05/89)
In article <594@cybaswan.UUCP> iiitsh@cybaswan.UUCP (Steve Hosgood) writes:
<I guess that an extension of the form:
<
< if (errval(foo = bar())) {
< <error code goes here>
< <could use 'foo' to get more details of the error>
< }
<
<..would be most acceptable. 'errval' could be made a reserved word on new
<systems (tests the carry bit), and implemented as a macro on older ones for
<backward compatability:
<
<# define errval(x) (x) < 0
<
<..or
<
<# define errval(x) (x) == -1
<
<..or something like that, though some sort of cast will be reqd of course.
How about:
#define errval(x) (errno = 0, (x), errno)
It'll even work on the current standard. Whether you can get this to
turn into tweaks to the carry flag (I hope that nobody would advocate
referring to hardware flags in the standard; there's already hardware
that C runs on without such flags) in a standard-conforming compiler
is an interesting question.
<mike
--
Can't buy happiness no matter what you do Mike Meyer
Can't get to heaven on roller skates mwm@berkeley.edu
Can't take a taxicab to Timbuktu ucbvax!mwm
Life is hard. mwm@ucbjade.BITNET
david@psitech.UUCP (david Fridley) (08/06/89)
variable, which makes the function not reenterant or relocateable. (Unless you have the hardware and CPU power to support virtual memory and tasking.) The problem with #define errval(x) if(x<0) is that in many systems the stack is around the top of memory, and therefore many stack variables would be negative. The MAGIC_1 idea seems good, you are just trying to identify values that pointer can not have. If we use #defines for thes values and put them in errno.h then the function will be common across systems even if the values are not. Wouldn't it be nice if you could return more than one value from a C function? ie: (ret1,ret2)=func(param1,param2,param3); I believe this would solve are error problems, and many others that I have had. -- david. DISCLAIMER: If it's important have a backup. If it ain't broke don't fix it. Proceed at your own risk. My oponions are MY own. Spelling does not count. My fondest dream is to leave this planet.
henry@utzoo.uucp (Henry Spencer) (08/06/89)
In article <8314@boring.cwi.nl> siebren@piring.cwi.nl (Siebren van der Zee) writes: >>[errval(foo())] >Ok, and now the hard part: what should the code from the >CALLED function look like? The obvious thing to do is to have two different kinds of "return" statement, one for normal and one for errors. That completely hides how the "error" flag is passed back. Unfortunately, it is awkward on some machines, where there are no condition codes. Interested parties, note: the idea is *guaranteed* to go nowhere unless you are interested enough to implement it in a compiler. -- 1961-1969: 8 years of Apollo. | Henry Spencer at U of Toronto Zoology 1969-1989: 20 years of nothing.| uunet!attcan!utzoo!henry henry@zoo.toronto.edu
gregg@cbnewsc.ATT.COM (gregg.g.wonderly) (08/07/89)
From article <8314@boring.cwi.nl>, by siebren@piring.cwi.nl (Siebren van der Zee): > iiitsh@cybaswan.UUCP (Steve Hosgood) writes: >>[errval(foo())] > Ok, and now the hard part: what should the code from the > CALLED function look like? I have always liked the idea of having the types of information that VMS provides in condition codes. Given the ability to return a relatively large integer, or structure, it is simple enough to have something like struct errcode { int pad:3; /* Additional information. */ int fac_id:11; /* 2048 possible facility codes. */ int error:14; /* 16384 possible errors per facility. */ int sever:4; /* Severity bits. */ }; The sever field is the best part. It contains one of the following values. 1 == success 3 == warning 4 == error 5 == informational 8 == fatal This leaves you with an easy check for errors. Is bit 0 set? The VAX instruction, blbs (branch low bit set), is used all through VMS for this purpose. I have written a program to generate error message declarations in C given a simple input format of the string, a mnemonic and the severity of the message (along with the facility id). The VMS file format is simply .facility <nnn>,SS$_ .success mnemonic <string inside less-than/greater-than brackets> mnemonic <string inside less-than/greater-than brackets> mnemonic <string inside less-than/greater-than brackets> .fatal ... ... .informational ... ... .warning ... ... .error ... ... The result is that a variable by the name of SS$_mnemonic is generated that contains the value that would be generated if the above structure was actually a single 4-byte integer. Now for the tough part. The VMS linker understands named sections in the object file and sections can have attributes, such as appended. The magic here is that all message sections have the same name and the attribute append. The error message formatter, sys$errmsg(), knows how to get to this section of the program and how to look through the generated tables of messages. So, if you pass it an integer, it starts at the front of the table and looks for the table associated with the facility-id. If then indexs into the table based on the error message number field and gets the text. The severity is just used to generate the appropriate severity character in the message. The mnemonic is generated in the message so that you can actually search the source for the use of a message to aid in finding the messages origin when necessary. The result is something like %SYSTEM-F-BADPARAM, insufficient parameters to system call In my particular implementation, the corresponding unix format message would be system: fatal, BADPARAM, insufficent parameters to system call Like VMS provides the SET MESSAGE command to alter the format of the message, I made use of the ERRMSK environment variable to allow the 4 different fields to be selected by bits in the mask. By default, a unix format message (you can select VMS style too) has the mask value of 9, so the above message would look like system: insufficient parameters to system call. The formatting routine uses varargs so that parameters can be provided. -- ----- gregg.g.wonderly@att.com (AT&T bell laboratories)
peter@ficc.uu.net (Peter da Silva) (08/07/89)
In article <26998@agate.BERKELEY.EDU>, mwm@eris.berkeley.edu (Mike (I'll think of something yet) Meyer) writes: > #define errval(x) (errno = 0, (x), errno) This is how you get programs that spit out messages like: "peter@ficc.uu.net: Not a tty" I'll leave the whys and wherefores as an excersize for the reader, or you could just look it up in your comp.lang.c archives around February. -- Peter da Silva, Xenix Support, Ferranti International Controls Corporation. Business: peter@ficc.uu.net, +1 713 274 5180. | "The sentence I am now Personal: peter@sugar.hackercorp.com. `-_-' | writing is the sentence Quote: Have you hugged your wolf today? 'U` | you are now reading"