The strerror function maps an error number into a string description of that error.

char *
strerror(int errnum);

It returns a pointer to the string representation of the error, the contents of which are implementation-defined.

Local Variables

We'll use a local variable to point to the string description corresponding to the received error number. This let's us modify what string is pointed to and have a single return statement (as we'll see shortly).

char *str = NULL;

Error Checking

No error checking is necessary for this function, or more accurately, the error checking will be handling by a switch statement that maps the error number to a string description.

Implementation

The total number of error numbers supported by the implementation is only two at this point (EDOM and ERANGE from errno.h), however it's is expected to grow in the future. This presents a good use case for a switch which makes for a cleaner implementation over the use of a large chain of if/else if/else statements. As more error numbers are defined in the future, new cases will be added to translate them.

If the error number is unknown we'll still translate this into a message indicating as such. This way our implementation always returns a description. After the switch, return the pointer to the string that was chosen.

switch (errnum)
{
case EDOM:
    str = "EDOM - An input argument is outside the domain over which the mathematical function is defined";
    break;

case ERANGE:
    str = "ERANGE - The result of the function cannot be represented as a double value";
    break;

default:
    str = "E??? - Unknown error number";
    break;
}

return str;

It's worth mentioning a short side note on style here. When possible, welibc chooses to limit the width of code to 80 characters which aids in readability. The C language supports splitting these long descriptions across multiple lines which might look like the following:

switch (errnum)
{
case EDOM:
    str = "EDOM - An input argument is outside the domain over which the " \
          "mathematical function is defined";
    break;

/* ... */

Although this maintains the 80-character width, it presents a problem when searching through the source code with a tool like grep.

If you were interested in where this error message came from then you might grep for the string "outside the domain" which would get you to the right place. However, if you chose to search for "the mathematical function" then your search wouldn't return any results because that string wouldn't exist on a single line within the welibc code base. For that reason, I consider it to be worth breaking the 80-character width to ensure easy searching later on.

Testing

Since the strings returned by strerror are implementation-defined, we can't test the contents of the strings themselves - we can only test that a string was returned. This simplifies the tests as we only need to check that the returned pointer is not a null pointer. We'll test the currently supported errno values in addition to the unsupported error number 0.

int
strerrorTest(void)
{
    int errnums[]   = { 0, EDOM, ERANGE };
    size_t i        = 0;
    int ret         = 0;

    for (i = 0; i < sizeof(errnums)/sizeof(errnums[0]); i++)
    {
        if (!strerror(errnums[i]))
        {
            ret = 1;
            break;
        }
    }

    return ret;
}

Conclusion

Unfortunately, strerror is a somewhat boring library function. The implementation chooses how to represents each error number as a string and returns those representations as appropriate.

char *
strerror(int errnum)
{
    char *str = NULL;

    switch (errnum)
    {
    case EDOM:
        str = "EDOM - An input argument is outside the domain over which the mathematical function is defined";
        break;

    case ERANGE:
        str = "ERANGE - The result of the function cannot be represented as a double value";
        break;

    default:
        str = "E??? - Unknown error number";
        break;
    }

    return str;
}
comments powered by Disqus