I am writing a C program in Eclipse editor. My C program requires me to write a multi-line macro. I want to write a code like:
#define my_Macro() \
struct my_Struct \
{ \
int a; \
float b; \
}; \
But as the macro is large so I have to make sure that I insert a \ at end of each line (for compiler to know that macro is continued). So my question is: Does eclipse/CDT provides any way such that \ is automatically inserted till the point the code is part of macro?
No, there is no such built-in functionality from Eclipse.
Related
This question already has answers here:
Multi line preprocessor macros
(7 answers)
Closed 1 year ago.
I am reading through the source code from Linux 0.11 and I came about this block of code in unistd.h:
#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
type name(atype a,btype b,ctype c) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)),"d" ((long)(c))); \
if (__res>=0) \
return (type) __res; \
errno=-__res; \
return -1; \
}
What does the symbol \ mean at the end of each line?
OK, see that #define at the first line? it means we are talking about the "C PreProcessor"
So, it is basically defining an "alias" for something (in this case, for _syscall3(type,name,atype,a,btype,b,ctype,c)).
It will replace every occurrence of the defined string, with its alias, anywhere it finds it in the source code. BEFORE the compiler begins to parse the code, do the compiler will read the long version.
Since the pre-processor in theory handles one line/command at the time, but humans are terrible reading LONG strings, we have the \ to 'concatenate' all those lines into a single line. Now we can actually read the code!
So, to answer your question: The \ means the line will continue below.
A macro ends with the end of the line. This would create realy long lines. To avoid this you can extend the line with .
#define add(a,b)\
((a)+(b))
is the same as
#define add(a,b) ((a)+(b))
I'm using Oxygen with CDT 9.3.0 built-in.
When I use a macro I defined that uses _Generic, all those macro uses are underlined with "syntax error", but the project compiles fine (which is setup to use my makefiles).
After reading a similar so question, and since _Generic begin from C11 possibly not supported by eclipse's code analysis, I tried defining a symbol for my macro definition to empty but it didn't work. (At project settings, C/C++ General->Paths and Symbols->Symbols Tab, GNU C, added symbol CONVERT(...) without a value and added a symbol CONVERT(X), and CONVERT() and CONVERT without a value).
For example my macro is:
#define FIRST_(_1, ...) _1
#define FIRST(...) FIRST_(__VA_ARGS__, _1, _2, _3)
#define CONVERT(...) \
_Generic((FIRST(__VA_ARGS__)), \
char* : toText, \
int : toInt, \
) (__VA_ARGS__)
and usage point, that gives the syntax error:
void* test = CONVERT("testme");
As #ErikW pointed out, _Generic is a C11 feature that Eclipse CDT's parser does not support yet. This bug tracks adding support for it.
(By the way, contributions to Eclipse CDT's C11 support are very welcome!)
It is possible to work around this using macros.
The problem with trying to define another version of the CONVERT(...) macro in "Paths and Symbols" is that the macros defined there are treated as if you wrote them at the very top of your file. A subsequent redefinition in your actual code overwrites the definition from "Paths and Symbols".
I can think of two approaches to go about this:
Approach 1
CDT defines a special macro __CDT_PARSER__ which evaluates to true when it's parsing the code, but false when the code is actually compiled.
You can take advantage of this to define a different version of CONVERT(...) for CDT's purposes:
#ifdef __CDT_PARSER__
#define CONVERT(...)
#else
#define CONVERT(...) \
_Generic((FIRST(__VA_ARGS__)), \
char* : toText, \
int : toInt, \
) (__VA_ARGS__)
#endif
This almost works, but not quite. We still get a syntax error, because this line:
void* test = CONVERT("testme", 42);
will now expand to:
void* test = ;
As you can see, we don't actually want an empty expansion for CONVERT(...). We want an expansion that will parse as a variable's initializer. 0 will work:
#ifdef __CDT_PARSER__
#define CONVERT(...) 0
#else
...
#endif
Approach 2
Instead of defining a different version of CONVERT(...), we could define _Generic(...) itself to be a macro for CDT's purposes.
This time, we can do it in "Paths and Symbols", because there is no redefinition of _Generic(...) in the code that would mess it up.
So let's define a symbol in "Paths and Symbols", with _Generic(...) as the name and an empty value.
Now, this line:
void* test = CONVERT("testme", 42);
will expand to:
void* test = _Generic((FIRST("testme", 42)), \
char* : toText, \
int : toInt, \
) ("testme", 42)
which will in turn expand to:
void* test = ("testme", 42);
which parses (("testme", 42) parses as a parenthesized comma-expression and is thus a valid initializer).
This approach has the advantage that you don't need to modify your actual code, and that it handles all uses of the _Generic macro rather than just the one in CONVERT.
On the other hand, it's possible that for some other uses of the _Generic macro, this particular expansion won't parse. If that's the case, you might be able to come up with a different expansion that will parse for all uses, or else you can go with Approach 1.
I am trying to write some reusable generic type-safe code in C, using macros, similar to how klib works:
#define Fifo_define(TYPE) \
\
typedef struct { \
TYPE *head; \
TYPE *tail; \
size_t capacity; \
} Fifo_##TYPE, *pFifo_##TYPE; \
\
inline Fifo_##TYPE * Fifo_##TYPE##_init(size_t capacity) { \
Fifo_##TYPE * fifo = calloc(1, sizeof(Fifo_##TYPE)); \
TYPE * data = calloc(capacity, sizeof(TYPE)); \
fifo->head = data; \
fifo->tail = data; \
fifo->capacity = capacity; \
}
// define macros
#define Fifo(TYPE) Fifo_##TYPE
#define Fifo_init(TYPE, capacity) Fifo_##TYPE_init(capacity)
And then I just use it with any type parameter:
Fifo_define(int32_t);
...
Fifo(int32_t) *myFifo = Fifo_init(int32_t, 100);
However, writing this is rather convoluted and error prone, with no IDE editor support (IntelliSense), so I wondered if there are any tricks which might allow me to (perhaps) add a few defines and then include the file, without having to end each line with \?
Something like:
// no idea how to do this, just checking if similar concept is possible
#define FIFO_TYPE int
#define FIFO_NAME Fifo_int
#include <generic-fifo.h>
#undef FIFO_NAME
#undef FIFO_TYPE
And I would somehow get all the right structs and functions. The problem is that there is a lot of parameter concatenation in these macros, so I am not sure if this can be done in a simpler manner than the first snippet?
Not really recommended in this case, but you can do something like what you want to achieve with X-macros:
#define SUPPORTED_TYPES \
X(int) \
X(double) \
X(char)
#define X(TYPE) \
typedef struct { \
TYPE *head; \
TYPE *tail; \
size_t capacity; \
} Fifo_##TYPE, *pFifo_##TYPE;
SUPPORTED_TYPES
#undef X
#define X(TYPE) \
inline Fifo_##TYPE * Fifo_##TYPE##_init(size_t capacity) \
{ \
Fifo_##TYPE * fifo = calloc(1, sizeof(Fifo_##TYPE)); \
TYPE * data = calloc(capacity, sizeof(TYPE)); \
fifo->head = data; \
fifo->tail = data; \
fifo->capacity = capacity; \
}
SUPPORTED_TYPES
#undef X
But this didn't really improve the situation all that much. It got rid of the need for a single, ugly Fifo_define macro, so you can split up the code in several sections. But the macro mess remains.
I would recommend some completely different approach. Two suggestions:
Handle the type-generic things in the classic C way, in run-time. Use callbacks. Keep track of the used type with an enum, if needed.
C11 _Generic allows all kinds of type safety tricks and can be used to phase out such messy macros. Example that implements "functors". The macro itself is kept minimal and the different implementations for various types is typed out. (That's usually what you end up doing anyway, when you do type-generic programming.)
If you are using complex macros, consider using m4 instead of the C pre-processor. m4 is similar to the C pre-processor but is much more powerful and can do things like have multiple lines without a line continuation character.
Using code generators like m4 is called meta-programming.
Using m4 in C can be accomplished by treating it as a pre-pre-processor like this:
% grep -v '#include' file1 file2 | m4 > outfile
% m4 file1 file2 | cc
Since m4 works in a similar way to the C pre-processor at the basic level, it will generally convert any ordinary C macros correctly in addition to supporting its own advanced features.
I would like to define a template like this:
#define DECLARE_MY_STRUCT(name) \
#ifndef MY_STRUCT_DECLARED \
struct my_##name##_struct { \
double var; \
}; \
#define MY_STRUCT_DECLARED \
#endif
This would allow me to use DECLARE_MY_STRUCT template wherever I want and not get "my_struct was already defined" error.
Unfortunately, gcc treats #ifndef as its preprocessor directives instead of part of template declaration and fails to build such code. Any way to workaround this?
( Except for using
#ifndef MY_X_STRUCT_DECLARED
DECLARE_MY_STRUCT(X)
#endif
as there may be a lot of different struct names.
)
The C Standard does not allow nested pre-processor directives, so this is impossible. The # in #ifndef would be treated as a stringizing #.
I declare macros which would make it easy to replicate the logic of writing to a file Log
I end up getting the error C2065: 'flog' : undeclared identifier.
But I don't get this error for log_buffer.
I am using Visual Studios 2008 IDE.
What am i doing wrong?
#ifndef ERROR_LOG_MACRO
#define ERROR_LOG_MACRO 1
#define SETERRORPARAMS char log_buffer[MAX_PATH]; \
char flog[MAX_PATH]; \
FILE *err_log_fp;
/*
Arguments: x (Name of the File)
y (File Path without the Filename)
z (Mode)
*/
#define OPENFILE(x,y,z) strcpy(flog,y); \
strcat(flog,"\\"); \
strcat(flog,x); \
err_log_fp = fopen(flog, z);
#define WRITELOG(x) if(err_log_fp) \
fwrite(log_buffer, sizeof(char), strlen(log_buffer), err_log_fp);
#define CLOSEFILE if(err_log_fp) \
fclose(err_log_fp);
#endif
I even tried to do
#define OPENFILE(x,y,z) SETERRORPARAMS \
... \
But even this did not work.
You probably have trailing whitespaces after the first line of your macro:
#define SETERRORPARAMS char log_buffer[MAX_PATH]; \______ <-- make sure you have no whitespaces
char flog[MAX_PATH]; \
FILE *err_log_fp;
Either that, or you're not using the macro and log_buffer is declared elsewhere.
Have you actually checked that flog is in scope wherever you're using the OPENFILE macro?
Such as with the code segment:
SETERRORPARAMS
OPENFILE (fileStr, pathStr, modeStr)
Worst case, you'll have to examine the code after the preprocessor has done its work. Most compilers will let you examine the output produced by that preprocessor stage. GCC would use gcc -E but I'm not sure what the equivalent is to MSVC.
This link seems to indicate you can enter /P into the project settings to get the preprocoessed files written to *.i files.
But, I've got to say this, using macros for this is not really a good idea. In the old days, it used to be good for speed purposes but it's not really necessary in these days of inline functions and very good code optimisers.