how to debug macro? - c

having this code:
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#define check(x) ({int _val = (x); (_val ==-1? \
({fprintf(stderr, "Error (" __FILE__ ":%d) -- " \
"%s\n",__LINE__,strerror(errno)); \
exit(-1);-1;}) : _val); })
int main (int argc, char **argv) {
if (argc!=2){
fprintf(stderr, "usage: %s <filename>\n", argv[0]);
exit(-1);
}
int fd;
fd=open(argv[1], O_RDONLY);
if(fd<0){
perror("open");
fprintf(stderr,"errno = %s\n",strerror(errno));
exit(-1);
}
for(char c;check(read(fd,&c,1))>0;) //macro "check(x)" HERE
fputc(c,stdout);
return 0;
}
It compiles without an error, but I can see the macro does not output error messeges (__FILE__, neither __LINE__), as define it the macro. How to fix that? (And for general, how to debug macro, how at least output some error for it)?
$cc -pedantic a.c
a.c: In function ‘main’:
a.c:10:2: warning: ISO C forbids braced-groups within expressions [-Wpedantic]
({fprintf(stderr, "Error (" __FILE__ ":%d) -- " \
^
a.c:30:13: note: in expansion of macro ‘check’
for(char c;check(read(fd,&c,1))>0;)
^~~~~
a.c:9:18: warning: ISO C forbids braced-groups within expressions [-Wpedantic]
#define check(x) ({int _val = (x); (_val ==-1? \
^
a.c:30:13: note: in expansion of macro ‘check’
for(char c;check(read(fd,&c,1))>0;)
not single mention about for loop (only its location, because the macro is in there, but that is not error) statment. Only about macro. So please focus on macro problem and not about the for loop.
EDIT1:
the macro actually comes from this guy:
youtube tutorial (at the end of the video), well he uses clang, so I do not know what clang uses as a preprocessor (and therefor it works for him).
EDIT2 (output from a.i - preprocessed output):
# 304 "/usr/include/fcntl.h" 3 4
# 8 "a.c" 2
# 14 "a.c"
int main (int argc, char **argv) {
I have deleted all the noise. But you can see between #include <fcntl.h> and int main, there is nothing. But there should be the #define check(x).... So it does not tell me WHY is it missing.

how to debug macro?
Read more about C, in particular the Modern C book then this site.
Most C compilers have a way to show the preprocessed form of a translation unit.
Read the documentation of your C compiler.
For GCC, see this. For Clang, see that. The GCC preprocessor is documented here.
If you use gcc as your C compiler on file foo.c run it as gcc -C -E -H -Wall foo.c > foo.i to obtain into foo.i the preprocessed form of foo.c (but most comments are kept, and you could add more of them). Then look with a pager or an editor (I recommend GNU emacs, but feel free to use vim, gedit, more, less, most etc...) into that generated foo.i file.
I can see the macro does not output error messeges
A macro is not outputting any messages, it is just expanded.
If you use a build automation tool such as GNU make or ninja, read its documentation.
If you use some IDE, read its documentation. Many IDEs offer a way to show the preprocessed form, and some might even make the macro expansion on the fly.
Don't forget that in some cases, you may want to use some other preprocessor, such as GPP or GNU m4, or generate some C code programmatically (like GNU bison, or lemon, or SWIG does). Many transpilers (such as Chicken-Scheme or Bigloo) are generating C code, and in Bismon I am doing that at run time, then dynamically loading the generated plugin, using dlopen(3). In RefPerSys we want to generate C++ code at runtime, and later use libgccjit.
You can find lots of open source C preprocessors, even standalone ones like mcpp. You could study their source code and improve them for your needs. And tinycc or nwcc is a small enough open source C compiler (with their preprocessor embedded inside) that you could improve in a few days.
If you use a recent GCC, you could extend it with your own plugin, perhaps adding your own _Pragma (used in your macros) which would display things after preprocessing.
Some clever debuggers (e.g. a suitably configured recent GDB) are capable of macro expansion (thrn compile your C code with gcc -O0 -g3 -Wall)
In Bismon, I use lots of quite long C macros. They might be inspirational. And so is the container-macros library. And also GTK whose macros are very readable.
My experience: to debug a macro, remove many lines from it, till you are satisfied with its expansion. Grow that macro in small steps. Use git on your source code.
$cc -pedantic a.c
I recommend using gcc -Wall -Wextra -g3 -H -pedantic a.c on Linux then use a recent gdb.

Generally speaking you can't debug a macro as macro is not something which is executed.
But there should be the #define check(x).... So it does not tell me
WHY is it missing.
Your macro was preprocessed - ie textually replaced by the preprocessor.
After the preprocessing it is expanded to:
for(char c;({int _val = (read(fd,&c,1)); (_val ==-1? ({fprintf(
stderr
, "Error (" "./example.c" ":%d) -- " "%s\n",30,strerror(
(*__errno_location ())
)); exit(-1);-1;}) : _val); })>0;)
fputc(c,
stdout
);

You can't debug a macro in the sense that a high level debugger will step through the macro code. What you can do is temporarily expand the macro in the source code and use a debugger to see what is going wrong.
One idea is to use a code formatter, like clang-format to beautify the macro so that you can understand it better an use the debugger. Applying this idea, transform the macro into a function and let the formatter do its job:
$ clang-format -i macro.c
results in:
void check1(x) {
({
int _val = (x);
(_val == -1 ? ({
fprintf(stderr,
"Error (" __FILE__ ":%d) -- "
"%s\n",
__LINE__, strerror(errno));
exit(-1);
-1;
})
: _val);
})
}
The code you originally posted actually compiles and executes properly here. I made a version with a few cuts to be able to test the macro:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define check(x) ({int _val = (x); (_val ==-1? \
({fprintf(stderr, "Error (" __FILE__ ":%d) -- " \
"%s\n",__LINE__,strerror(errno)); \
exit(-1);-1;}) : _val); })
int main (int argc, char **argv)
{
check(-1);
return 0;
}
results in:
$ gcc a.c && ./a.out
Error (a.c:13) -- Success

This may be a little late, but I wanted to say that you didn't place a check where you want the code to be checked (opening the file).
Change this:
fd = open(argv[1], O_RDONLY);
To this:
check(fd=open(argv[1], O_RDONLY));
That's what Jacob is doing in its video. He is additionally adding the check in the read operation, but that's completely secondary and aimed to catch errors that came after the file was opened successfully (No example of this kind of errors was shown in the video).

Related

GCC __func__ gets evaluated to an empty string

Given the following code in a project I'm working on:
/* Pre-definitions in a pre-definitions file to be included in the project */
#ifdef WIN32
#define __FUNCNAME__ __FUNCTION__
#else
#define __FUNCNAME__ __func__
#endif
/* My definitions */
#define MAC() \
MAC1()
#define MAC1() \
myPrintFunction(__FUNCNAME__)
/* My print function */
void myPrintFunction(const char * functionName)
{
printf("\n func name: %s \n",functionName);
}
/* Macro usage example function */
void myFunction()
{
if (some_condition)
{
MAC();
}
}
The function name is presented as an empty string.
Any idea why, and how can I fix it?
Code compiled and tested on Linux machine, using GCC compiler.
Use __func__ out of the box. It's been part of the C standard since C99. Change your compiler settings to use at least that standard.
Note that __func__ is not a macro but a predefined identifier which takes the form such that writing it anywhere within a function body is exactly equivalent to using it at that point, having first written
static const char __func__[] = "function-name";
just after the opening brace of a function body.
Formally the behaviour of your current code is undefined. Any symbol containing two consecutive underscores is reserved by the system. (That includes macro names, function names, and variable names.)
Your code as presented gives the expected result (once I'd added the necessary includes and main):
#include <stdio.h>
#ifdef WIN32
#define __FUNCNAME__ __FUNCTION__
#else
#define __FUNCNAME__ __func__
#endif
/* My definitions */
#define MAC() \
MAC1()
#define MAC1() \
myPrintFunction(__FUNCNAME__)
void myPrintFunction(const char * functionName)
{
printf("\n func name: %s \n",functionName);
}
int main()
{
MAC();
}
I compiled this using gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds with no warnings.
You should really post a complete (but minimal) example that actually compiles, along with the compiler flags you used, as something must certainly be different to explain the symptoms you describe.
Also, when writing statements as macros, you may find it helpful to use the do {...} while (0) idiom to avoid unexpected expansions changing the control flow.

C preprocessor Result

Which result does return this construct? I mean the result variable in main-function, and why?
I know, that the example is very strange ;)
header1.h file:
extern const int clf_1;
header2.c file:
#include "header1.h"
const int clf_1 = 2;
test.h file:
#include <header1.h>
#define xyz clf_1
#define NC_CON 2
#if (xyz== NC_CON)
#define test 40
#else
#define test 41
#endif
C file
#include <header1.h>
#include <test.h>
int main(int argc,char *argv[])
{
int result = 0:
if (test == 40)
{
result = 40;
}
}
Read the wikipage on the C preprocessor and the documentation of GNU cpp (the preprocessor inside GCC, i.e run by gcc or g++ etc...). It is a textual thing, and it is run before the definition const int clf_1 = 2; has been processed by the compiler. A #if directive only makes sense if all the names appearing in it are preprocessor symbols (defined with #define or with -D passed on the command line of the GCC or Clang/LLVM compiler)
Use gcc -C -E yoursource.c > yoursource.i (with some other options after gcc, probably -I. is needed ... you should #include "header1.h"
etc...) then look with an editor or a pager into the generated yoursource.i (the preprocessed form)
The world would be very different if the C preprocessor transformed ASTs; for historical reasons, the first C preprocessors were textual filters (run as a different program).

Are #include directives processed prior to macro expansion regardless of their location within a file?

I came across some code the other day that was similar to the following (the following has been over-simplified for the sake of brevity):
config.h
#ifndef __CONFIG__
#define __CONFIG__
#define DEVELOPMENT_BLD _TRUE_
#if (DEVELOPMENT_BLD == _TRUE_)
#define FILE_EXT ".dev"
#else
#define FILE_EXT ".bin"
#endif
#define PROJECT_STRING "my_project"
#define FILE_NAME PROJECT_STRING FILE_EXT
/* Common include files */
#include "my_defs.h"
#endif /* __CONFIG__ */
my_defs.h
#ifndef __MY_DEFS__
#define __MY_DEFS__
#define _TRUE_ 1
#endif /* __MY_DEFS__ */
The project had always compiled without any issues, but since I made some minor changes (and the actual project was rather large) I decided to run Lint on it. When I did, I received the following error:
Warning 553: Undefined preprocessor variable '_TRUE_', assumed 0
I then wondered why the compiler didn't catch that _TRUE_ is defined in my_defs.h which is included after the macro's first usage. So I compiled it on a different compiler with the same results - succesful compilation, no warnings and FILE_NAME was correctly evaluated regardless of how I set DEVELOPMENT_BLD (using _TRUE_ or !_TRUE_). Here are my two compiler settings:
ArmCC -c -cpu Cortex-M3 -g -O0 --apcs=interwork -I "..\ARM\CMSIS\Include" -I "..\ARM\INC\NXP\LPC17xx" -o "file.o" --omf_browse "file.crf" --depend "file.d" "file.c"
mingw32-gcc.exe -pedantic -Wall -g -c D:\dev\practice\header_question\main.c -o obj\Debug\main.o
I decided to run a simple test to see if the value of FILE_NAME was being properly evaluated by the preprocessor. I also wanted to see what the value of DEVELOPMENT_BLD actually was. I ran the following code two times:
main.c
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("FILE_NAME:%s, WHAT_IS_TRUE:%d", FILE_NAME,DEVELOPMENT_BLD);
return 0;
}
The first time I used the value #define DEVELOPMENT_BLD _TRUE_ with this result:
FILE_NAME:my_project.dev, WHAT_IS_TRUE:1
The second time I used the value #define DEVELOPMENT_BLD !_TRUE_ with this result:
FILE_NAME:my_project.bin, WHAT_IS_TRUE:0
My first thought was that perhaps _TRUE_ was being defined elsewhere - so just to be sure I commented out #include "my_defs.h". I then began to receive a compiler error:
error: '_TRUE_' undeclared (first use in this function)
All of that leads to my question. Are #include statements required to be evaluated by the preprocessor before macro expansion or did I just get lucky?
The C pre-processor acts on directives as it encounters them. In this context, the warning is correct; at the time you use #if DEVELOPMENT_BUILD == _TRUE_, the effective value of _TRUE_ is zero. However, because of the #define DEVELOPMENT_BUILD _TRUE_ definition, the preprocessor is evaluating #if 0 == 0, which is true. However, you'd have had the same result if you'd specified #define DEVELOPMENT_BUILD _FALSE_ because _FALSE_ would also be implicitly 0 and hence the test would be #if 0 == 0 again (which also evaluates to true). If, when the preprocessor has finished evaluating expressions in the #if condition, there are identifiers left over, they are implicitly assumed to be 0.
Note that names starting with an underscore and a capital letter or another underscore are reserved for any use by the implementation. You are treading on very thin ice with your choice of names such as _TRUE_ and __CONFIG__. (Just because system headers use names like that is not a good reason for you to do so — in fact, quite the opposite. The system headers are carefully keeping out of the namespace reserved for you to use; you should keep out of the namespace reserved for the system.)

gcc warnings for no-effect statements.

I have a logging macro which in release mode becomes:
#define LOG (void)
So statement
LOG("foobar %d", 0xbabecafe);
is expanded to
(void)("foobar %d", 0xbabecafe);
The problem is that the last expression produces an warning under gcc:
warning: left-hand operand of comma expression has no effect [-Wunused-value]
How can I change the logging macro such that no warning is issued? (Note, that I don't want to add compiling flag -Wunused-value).
EDIT I see already a couple of answers involving (...). The same file is compiled under Minix which doesn't support variadic macros. The best would be to have a C89 conforming solution. While your answer is correct (and I upvoted it), it is my fault that I didn't include this small detail.
I think the old school way of dealing with this is to take advantage of double parens. Something like this:
LOG(("message: %d", 10));
Then for your macro, you define it like this:
#define LOG(x) printf x
or
#define LOG(x) (void)0
Because of the double parens, the pre-processor treats the whole inner paren as a single parameter. This at least used to work in visual studio.
EDIT: I did a quick test, it works with gcc with -ansi, so it should be good:
gcc -DNDEBUG -ansi -pedantic -W -Wall test.c -o test
#include <stdio.h>
#ifdef NDEBUG
#define LOG(x) printf x
#else
#define LOG(x) (void)0
#endif
int main() {
LOG(("message: %d\n", 10));
return 0;
}
The easiest should be
#define LOG(...) (void)0
(gcc supports the C99 variadic macros and most other compilers also do these days) That will discard the arguments list, which has two advantages:
it does not create statements with no effect and
the arguments are not evaluated at all (if you call non-inline functions in the argument list, in your version the compiler can't eliminate them, while with the variadic macro, the compiler won't see them at all.
#define LOG(...) seems to do the trick.
For your problems with a non-conforming C implementation (not even C89?) you could do something like
static void LOG(char *format, ...) { /* empty */ }
even a completely dumb compiler should be able to optimize that out.
I've used
#define LOG( t) t
for the development version and
#define LOG( t)
for the release version, with a typical use being
LOG( printf( "here\n"));

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.

Resources