I'm writing a program where I need to do some shell path expansion, and I've decided to use wordexp(3)
for this. Since the argument I'm giving to it is user-provided, I would like to present a relevant error message in the case of a non-zero return value. However, I can't seem to figure out how I would do this. Based on my reading of the manual page for this function, it doesn't seem to make use of errno
, so I can't use perror()
. I can't print the constant values it provides either since they just are integers at runtime.
How can I get a string representation of the error return values?
Regarding printing some enum error codes that are essentially just integers: just make a string table of error messages and print the one you want based on the error code.
Solution 1
It could be semi-automated somewhat by using "X macros":
#include <wordexp.h>
#define WORDEXP_RESULT(X) \
/* code custom error message */ \
X(WRDE_BADCHAR, "Bad char is bad!") \
X(WRDE_BADVAL, "Bad value is bad!") \
// and so on...
Then you'd call the function and check the result, for example with a switch
:
int result = wordexp(...);
switch(result)
{
case 0: /* ok */ break;
WORDEXP_RESULT(WORDEXP_ERR_CASE)
};
Where the macro list boils down to some convenient macro:
#define WORDEXP_ERR_CASE(val, str) \
case (val): \
{ \
fprintf(stderr, \
"Error: wordexp failed. Code: %s. %s", \
#val, str); \
break; \
}
Output from this will look like:
Error: wordexp failed. Code: WRDE_BADCHAR. Bad char is bad!
The advantage of the X macro here is that you get a direct coupling between the wordexp.h
error codes and your error messages, plus macros mean we can "stringificate" the enumeration constants.
Solution 2
Although I cheated and took a peek at what these enums expand to. It turns out they are adjacent number from 1 to upward. So we could actually get rid of the switch
without getting a huge string table. And at the same time write something more readable than X macros:
if(result != 0)
{
const char* wordexp_errmsg[] =
{
[WRDE_BADCHAR] = "Bad char is bad!",
[WRDE_BADVAL] = "Bad value is bad!"
};
fprintf(stderr, "Error: wordexp failed. %s\n", wordexp_errmsg[result]);
}
This has a coupling between error codes and strings too, but we lose the handy stringification of the enumeration constants themselves.