[comp.std.c] Error Return

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"