C: How to enable __<Flag_Name>__ - c

I have the following piece of code:
#ifdef __SYM_TRACE__
#define SYM_TRACE( L, F ) { SETTRACE_LEVEL(L); tracefunc F; }
#define SYM_TRACE2( F ) { SETTRACE_LEVEL(SYM_MODULE); tracefunc F; }
#else
#define SYM_TRACE( L, F )
#define SYM_TRACE2( F )
#endif
Now the issue is that where would I find the SYM_TRACE flag and how do I enable it? There is no macro in the code by the name of SYM_TRACE, so where is this getting picked from?
Also, another beginner question. Could someone please explain the significance of __ before and after the macro name.
Thanks,
Sunny

Answer is already there so consider it just as addition
You can do following option to enable __SYM_TRACE__
write #define __SYM_TRACE__ in header file which is getting used with shown piece of code.(Do not forget to guard it with #ifndef endif)
You can add it in Makefile as suggested by #Ishmeet using -D__SYM_TRACE__
Now if you are talking about _Name_ then it is a way to make difference between standard(or predefined) macros with user defined.For example GCC predefined macros like __WCHAR_TYPE__ and __WINT_TYPE_ having underscore before and after.

__SYM_TRACE__
is probably defined in your make file, and __ is just the name, I dont think that has a significance, maybe it does during porting on other platforms.
Most C compilers accept the option -D to define a symbol:
gcc -D__SYM_TRACE__ file.c

Related

Why only define a macro if it's not already defined?

All across our C code base, I see every macro defined the following way:
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
#ifndef BEEPTRIM_ROLL_RATE_DEGPS
#define BEEPTRIM_ROLL_RATE_DEGPS 0.2f
#endif
#ifndef FORCETRIMRELEASE_HOLD_TIME_MS
#define FORCETRIMRELEASE_HOLD_TIME_MS 1000.0f
#endif
#ifndef TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS 50.0f
#endif
What is the rationale of doing these define checks instead of just defining the macros?
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#define BEEPTRIM_ROLL_RATE_DEGPS 0.2f
#define FORCETRIMRELEASE_HOLD_TIME_MS 1000.0f
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS 50.0f
I can't find this practice explained anywhere on the web.
This allows you to override the macros when you're compiling:
gcc -DMACRONAME=value
The definitions in the header file are used as defaults.
As I said in the comment, imagine this situation:
foo.h
#define FOO 4
defs.h
#ifndef FOO
#define FOO 6
#endif
#ifndef BAR
#define BAR 4
#endif
bar.c
#include "foo.h"
#include "defs.h"
#include <stdio.h>
int main(void)
{
printf("%d%d", FOO, BAR);
return 0;
}
Will print 44.
However, if the conditional ifndef was not there, the result would be compilation warnings of MACRO redefinition and it will print 64.
$ gcc -o bar bar.c
In file included from bar.c:2:0:
defs.h:1:0: warning: "FOO" redefined [enabled by default]
#define FOO 6
^
In file included from bar.c:1:0:
foo.h:1:0: note: this is the location of the previous definition
#define FOO 4
^
I do not know the context but this can be used to give the user the availability to override the values set by those macro definitions. If the user explicitly defines a different value for any of those macros it will be used instead of the values used here.
For instance in g++ you can use the -D flag during compilation to pass a value to a macro.
This is done so that the user of the header file can override the definitions from his/her code or from compiler's -D flag.
Any C project resides on multiple source files. When working on a single source file the checks seem to (and actually) have no point, but when working on a large C project, it's a good practice to check for existing defines before defining a constant. The idea is simple: you need the constant in that specific source file, but it may have been already defined in another.
You could think about a framework/library that gives to the user a default preset that allow the user to compile and work on it.
Those defines are spreaded in different files and the final user is advised to include it's config.h file where he can config its values.
If the user forgot some define the system can continue to work because of the preset.
Using
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
allows the user to define the value of the macro using the command line argument (in gcc/clang/VS) -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f.
There is another important reason. It is an error to re-define a preprocessor macro differently. See this answer to another SO question. Without the #ifndef check, the compiler should produce an error if -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f is used as a command line argument in the compiler invocation.

How do you enable "#ifndef/#endif" blocks in makefile builds?

I'm trying to enable debugging options in MuPDF. For some reason they have used #ifndef NDEBUG and #endif greying out code I want to use. I searched throughout the library but couldn't find any traces of NDEBUG defined anywhere. I've managed to work around this by adding #undef NDEBUG in a header, but I would like to know if there is a more non-intrusive method to do so.
SO, can you enable "#ifndef/#endif" blocks from the makefile?
Also, why would you use #ifndef to grey out code? Isn't it supposed to be #ifdef NDEBUG?
You can add -DNDEBUG to the following 3 variables - CFLAGS, CPPFLAGS and CXXFLAGS in your Makefile to define NDEBUG.
Which is equivalent to adding #define NDEBUG
There are other variations too:
-DNBDEBUG=1
is equivalent to
#define NDEBUG 1
And to answer the question of why would someone use #ifndef instead of #ifdef is because it highlights your modifications to the original code much clearly.
For example consider the following code as the original version:
int a = 123;
int b = 346;
int c = a + b;
And you need to add a macro DO_MULT which will multiply instead - there are 2 ways to do this.
First Variation:
int a = 123;
int b = 346;
#ifdef DO_MULT
int c = a *b;
#else
int c = a + b;
#endif
Second variation:
int a = 123;
int b = 346;
#ifndef DO_MULT
int c = a + b;
#else
int c = a *b;
#endif
If you use difftools to see the changes - the second variation will show the diff more clearly compared to the first one.
One more reason why you would use a #ifndef is to DO something in CATCH-ALL-EXCEPT scenarios.
#ifndef won't omit the code if the flag is defined, hence it's usage. You've managed to include the code using #undef.
Both #ifdef and #ifndef are useful, as justification consider this contrived example: you have a bunch of debug printf code that you only want to compile into a Debug build, using #ifdef DEBUG conditions. In the same executable you also have code that you want to leave out of a Debug build. In this case using #ifndef DEBUG is your only choice.
You can define such flags in the makefile, and you can also try to remove previous definitions by using -U. Look for a CFLAGS variable in the makefile and add -UNDEBUG, or add it directly to the compiler call in the compilation target.
If the flag is being defined somewhere in the source tree then this won't help.

Macro declaration giving errors

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.

C Macro - Dynamic #include

I'm trying to figure out how to build a variable string for the #include statement using GCC.
The idea is that for each source module I have written, I want to include as a header, a dynamically generated C source, that was created earlier in the build process.
Generating this file is not an issue. Including it, unfortunately, is.
What I have so far is (identities.h):
// identities.h
# define PASTER2(str) #str
# define PASTER(str) PASTER2(str ## .iden)
# define EVALUATOR(x) PASTER(x)
# define IDENTITIES_FILE EVALUATOR(__FILE__)
# include IDENTITIES_FILE
Ideally, this would be used like so (main.c):
//main.c
# include "identities.h"
int main() {return 0;}
Which would be expanded in a single pass by the preprocessor before compilation to yield:
//main.c (preprocessed)
# include "main.c.iden"
int main() {return 0;}
The two levels of indirection I'm using (PASTER and EVALUATOR) are a result of this post.
Unfortunately, this is not working and I am left with the error:
obj/win32/dbg/main.o
In file included from main.c:1:0:
identities.h:42:1: error: #include expects "FILENAME" or <FILENAME>
I think the problem is that the include statement is missing quotes.. Any ideas?
This is actually done in the Linux source tree; See line 100 of compiler-gcc.h.
#define __gcc_header(x) #x
#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)
#define gcc_header(x) _gcc_header(x)
#include gcc_header(__GNUC__)
I'm trying to figure out how to build a variable string for the #include statement using GCC.
This token pastes the value of __GNUC__ to a string; "linux/compiler-gcc" __GNUC__ ".h" and then stringifies the result. This maybe a gcc pre-processor extension.
Here is an example,
t1.h
#define FOO 10
t2.h
#define FOO 20
a.c
#ifndef VERSION
#define VERSION 1
#endif
#define __gcc_header(x) #x
#define _gcc_header(x) __gcc_header(t##x.h)
#define gcc_header(x) _gcc_header(x)
#include gcc_header(VERSION)
#include <stdio.h>
int main(void)
{
printf("FOO is %d\n", FOO);
return 0;
}
Here are two compiles,
g++ -o a a.cc
g++ -DVERSION=2 -o a a.cc
The output of either compile gives expected result.
As with the Linux source, you can key off of gcc pre-defined values. echo | g++ -dM -E - will give a list.
For your case, you can use the makefile to pass a define to the compile to allow dynamic inclusion of the generated header without altering the source. But then a simple alternative is just to run sed, etc on a template source file and replace it with the known include name.
Either technique is good for generating test fixtures, etc. However, for compiler feature discovery, this is a better method. For programmers who use IDEs, this might be their only choice.
I am fairly certain you can't do what you want, __FILE__ returns a string and ## works on tokens and there is no CPP string concat preprocessor macro. Normally this is gotten around due to the fact that two strings in succession e.g.
"Hello" " World"
will be treated as a single string by the C++ parser. However, #include is part of the preprocessor, and thus cannot take advantage of that fact.
Old answer:
Why are you doing this
{ #str, str ## .iden }
I'm certain that's not preprocessor syntax; what do you hope to achieve via that? Have you tried just:
str ## .iden
A '{' could explain the error you are getting.
What about BOOST_PP_STRINGIZE from the Boost Preprocessor library . It is specifically made to add quotes around a name.
Skipping the whole inclusion syntax thing for a while, I don't understand what your code is trying to do. You say:
# define PASTER(str) { #str, str ## .iden }
You give it main.c and expect "main.c.iden", but that returns {"main.c", main.c.iden }.
Are instead you looking for this?
#define PASTER2(str) #str
#define PASTER(str) PASTER2(str ## .iden)
You cannot use preprocessor like this. You have to supply a filename to the #include directive, it can't be some other macro.

I am a bit lost as to the meaning of this C preprocessor statement,

So, to start off, here's the code, with actual names switched for generic ones to limit confusion.
/* Get the list of Hotkey commands */
#define A_COMMANDS_MACRO(a, b, c, d) a = b ,
enum {
#include "commandsFile.def"
} ;
#undef A_COMMANDS_MACRO
This is a snippet from some source code I have been looking over and considering forking as a way to familiarize myself with the intricacies of the C programming language. So, to my untrained eye, this appears to do nothing. To my brain, defining something and then immediately undefining it would seem to cancel each other out.
Obviously, I realize that I'm wrong. But why am I wrong?
The "commandsFile.def" file probably uses the "A_COMMANDS_MACRO" macro somewhere internally.
Remember that "#include" essentially pastes the included file into the including one, so the #define is still in effect when "commandsFile.def" is processed.
What you see there is usually called X-MACRO. The technique consists in defining macros via #define, and then including a file that makes use of them with #include.
As a very simple example, you could have a header (say myheader.h) that declared 2 functions in the form of:
int foo(MYTYPE a, MYTYPE_PTR b);
void bar(MYTYPE a, MYTYPE_PTR b);
And then, in your code:
#define MYTYPE int
#define MYTYPE_PTR int*
#include "myheader.h"
#undef MYTYPE
#undef MYTYPE_PTR
The #undefs are sometimes in the included file as well.
For more information, take a look at this Wikipedia link.
The commandsFile.def should contain many lines:
A_COMMANDS_MACRO(A_COMMAND, 10, na, na)
A_COMMANDS_MACRO(OTHER_COMMAND, 23, na, na)
So that the code would create an enum with available commands and their codes.
It could be useful when this .def file is used by a program written in other language, so that instead of implementing text parsing, it uses C preprocessor to do this.

Resources