I am trying to create a function that will be generally used to determine if a file/directory exists, if it is within a certain path, and if it is of the specified type (S_ISREG, S_ISDIR, ...
Here are the parts of the source pertaining to this question:
int checkExists(const char *name, void *func(int))) {
struct stat st ;
int returnValue = DOES_NOT_EXIST ;
BOOL isInSourceHierarchy, isInTargetHierarchy ;
if (stat(name, &st) != -1) {
returnValue = EXISTS ;
if (memcmp(name, top_dir, strlen(top_dir)))
returnValue |= IN_SOURCE_STRUCTURE ;
if (memcmp(name, tgt_dir, strlen(tgt_dir)))
returnValue |= IN_TARGET_STRUCTURE ;
if (func != NULL) {
if (objType == func(st.st_mode))
returnValue |= RIGHT_TYPE ;
}
}
return returnValue ;
}
. . .
if (S_ISREG(0)) {} // Yes, I know, I know. This is for demonstration only.
if (checkExists(old, S_ISREG)) {
// Do something
} else { // Old file doesn't exist
// Do something else
}
When trying to compile this, I get:
linkStructure.c:642:31: error: ‘S_ISREG’ undeclared (first use in this function)
642 | if (checkExists(old, S_ISREG)) {
| ^~~~~~~
As can be seen, there is no complaint about the macro used as designed, of course. So my question is: Is there a way for me to reference the macro in my source like this? Or will I be left to basically emulate the macro in my function? (I suppose I could pass the expected type rather than the function, but for the sake of clarity, I would like to understand this limitation.)
It says S_ISREG
is undefined because the preprocessor doesn't ignore the parenthesis. #define FOO()
defines FOO()
, not FOO
.
Also, your function expects a function pointer as parameter, but macros are compile-time only symbols, you can't take its address.
But you can just wrap it in a function instead:
int isReg(int mode)
{
return S_ISREG(mode);
}
Now you can use it as you wanted:
checkExists(old, isReg);
And you keep the flexibility of your original code.