CBFalconer said:
There is no guarantee as to the value of EOF, other than that it is
negative. Any mapping into a size_t runs the risk of clashes. Use
an int to return EOF.
You could declare an enumerated type whose constants specify the
various error conditions. The values of the constants wouldn't have
to be consistent from one implementation to another, just their names.
It would be up to the implementer to avoid colliding with the value of
EOF. (EOF is -1 on every implementation I've ever heard of; a
programmer can't safely make that assumption, but an implementer can.)
For example:
enum {
ERROR_MAX = -2,
ERROR_FOO = -2,
ERROR_BAR = -3,
ERROR_BAZ = -4,
ERROR_XYZ = -5,
ERROR_MIN = -5
};
There's no tag for the enumerated type because it's used only to
declare a series of constants.
getdelim() could still return ssize_t (I've lost track, are we
assuming that ssize_t exists?), and it could be used like this:
ssize_t result = getdelim(arg1, arg2, arg3, arg4);
if (result >= 0) {
/* ... */
}
else if (result == EOF) {
/* ... */
}
else if (result >= ERROR_MIN && result <= ERROR_MAX) {
switch(result) {
case ERROR_FOO: /* ... */
/* ... */
default: /* ... */
}
}
This lets you squeeze valid results, EOF, and multiple error codes
into a single return value. It also assumes that losing half the
range of size_t isn't a problem.
I'm not claiming that this is a particularly good approach, just that
it's possible.