Hello,
The _kernel_ERROR macro is defined as (-2) by the header "kernel.h",
which is part of Acorn C/C++. I had never given much thought to its
correct usage until yesterday, when I was rewriting a signal handler
to comply with the spirit of this edict:
https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C....
(It says that behaviour is undefined if "...the signal handler calls
any function in the standard library other than the abort function,
the _Exit function, or the signal function with the first argument
equal to the signal number corresponding to the signal that caused the
invocation of the handler.")
I want to log debugging information in my signal handler. Since I'm
not allowed to use standard library I/O functions (or even the likes
of 'strcpy'), this is a bit tricky! I decided for the sake of my own
sanity that it is safe to call functions belonging to Acorn's language-
independent library kernel (e.g. _kernel_osgbpb, _kernel_osfind, etc.)
It would be nice if there were a list of asynchronous-safe functions,
but AFAIK there isn't. The result is that I've been using the library
kernel more than ever before.
Hitherto, I have always compared the return value of library kernel
functions with _kernel_ERROR, like in the following (invented)
function to flush the keyboard buffer:
bool flush_kb(void)
{
if (_kernel_osbyte(21, 0, 0) == _kernel_ERROR)
{
report_error(_kernel_last_oserror());
return false; /* failure */
}
return true; /* success */
}
The comments in the "kernel.h" header do not explain the significance
of return values between INT_MIN and -3 inclusive. They say ">= 0 if
the call succeeds... -1 if the call fails but causes no os error... -2
if the call causes an os error". The corollary of the first part of
the above description is that all values < 0 indicate failure of some
kind (in which checking for -2 in particular gives the wrong
semantics). However, the description is incomplete and an alternative
interpretation is that values < -2 have an undefined meaning.
I am curious to know how other people write code that calls library
kernel functions? Do you typically check for return value < 0 or
return value == _kernel_ERROR? Obviously, it depends partly on the
circumstances; a caller of _kernel_osfind might instead check for <= 0
since it can fail to open a file without causing an os error. But what
is standard practice?
I suspect the following version of my example function may be more
strictly correct, but I am loathe to adopt this practice because it
will make my code more bloated and (programmer) error-prone than
before:
bool flush_kb(void)
{
int e = _kernel_osbyte(21, 0, 0);
if (e < 0)
{
if (e == _kernel_ERROR)
report_error(_kernel_last_oserror());
return false; /* failure */
}
return true; /* success */
}
Incidentally, I am aware that _kernel_osbyte can never return a value
of -1; I just adopted it as a convenient example. The comments in
"kernel.h" merely state that "Not all functions are capable of
generating this result" - they don't guarantee that certain functions
will never do so. _kernel_osrdch, _kernel_osbget and _kernel_osgbpb
are all capable of returning -1. Of these, the most interesting is
_kernel_osrdch, which returns -27 if escape was pressed!
--
Christopher Bazley