Automatically inserting filename & line number in logging statements of a C program - c

I am writing a program for an embedded ARM processor in C. I would like to see the source filename and line number in the logging statements.
As the compiled code has no knowledge of line numbers and source files, I am looking for ways to have this inserted automatically before / during the compile process.
Are there any standard tools or compiler features that I can use for this?
I am using GCC.
For example:
This is what I would write in the source file:
log("<#filename#> <#linenumber#> : Hello World");
This is what would actually get compiled:
log("Foobar.c 225 : Hello World");

Typically you'd do something like this:
// logging function
void log(const char * file, const int line, const char *msg)
{
fprintf(stderr, "%s:%d: %s\n", file, line, msg);
}
// logging macro - passes __FILE__ and __LINE__ to logging function
#define LOG(msg) do { log(__FILE__, __LINE__, msg) } while (0)
Then when you want to log something:
LOG("We made it to this point!");
which will then generate a log message such as:
foo.c:42: We made it to this point!

There is a standard set of predefined macros as part of the preprocessor: https://gcc.gnu.org/onlinedocs/gcc-4.9.0/cpp/Standard-Predefined-Macros.html
The macros you want to use are __FILE__ and __LINE__ which are the file name and line numbers.

Related

How to exchange a string with an index during C preprocess

I have in several C-sources trace statements, like
TRACE(23, "abc");
TRACE(24, "def");
The numbers 23 and 24 are identifiers counted out of an automatically generated list containing in each line one string
...
"abc"
"def"
...
"abc" is in line 23 and so I write 23 in the appropriate trace statement.
The preprocessor generates me this wanted output
trace(23);
trace(24);
I think it should be possible to automate it in that way that I only write
TRACE("abc");
TRACE("def");
During C preprocessing i want to exchange the strings with the appropriate line number of my generated file automatically, so that I get in the preprocessor output
trace(23);
trace(24);
I can write a function which returns me the line number 23 for the string "abc" but I need to activate it during the preprocessing process. Are there any preprocessor hooks or other ideas?
The preprocessor supplies the automagic macros __FILE__ and __LINE__ (and a few others) which you can use:
#include <stdio.h>
#define TRACE(m) fprintf(stderr, "%s,%d: %s\n", __FILE__ , __LINE__, m)
int main(void)
{
int a;
if(a) TRACE("a");
else TRACE("no");
TRACE("returning");
return 0;
}
I have this idea now: Let the preprocessor generate this output:
trace("abc");
trace("def");
Than write a tool (i.e. a bash script with awk) exchanging the strings with their line number from the generated list file:
...
"abc"
"def"
...
And finally let the compiler do his work. I am not really happy with it, because it needs to be adapted for each compiler. Any better idea?

Know exact line of the program execution

I am trying to do a debug mode for my program that writes something like this in one file to store the logs:
[Day Month D HH:MM:SS YYYY] foo.c function_name line 33: The thing
that happens
The problem is know the exactly value of the line, obviously I can see it in my IDE, but I want to know if exist a more elegant and efficient way.
I hope you have explained me well (sorry if not) and thanks in advance.
You may have a look at macro assert (assert.h) where it is done as intended by you.
In short:
It has to be a macro. If it were a function it would report the file and line of this function but actually you would want the file and line where the function is called. (This does not mean that this macro cannot call a function as helper.)
The current file and line are accessible by the macros __FILE__ and __LINE__.
So this is how it could look in source code:
#define LOG_DEBUG(TEXT) log_debug(__FILE__, __LINE__, TEXT)
void log_debug(const char *file, int line, const char *text)
{
fprintf(stderr, "DEBUG '%s':%d: %s\n");
}
As MCVE test-log-debug.c:
#include <stdio.h>
#define LOG_DEBUG(TEXT) log_debug(__FILE__, __LINE__, TEXT)
void log_debug(const char *file, int line, const char *text)
{
fprintf(stderr, "DEBUG '%s':%d: %s\n", file, line, text);
}
/* test/sample */
int main()
{
LOG_DEBUG("in main()");
return 0;
}
Compiled and tested with gcc in cygwin on Windows 10 (64 bit):
$ gcc --version
gcc (GCC) 6.4.0
$ gcc -std=c11 -g -o test-log-debug test-log-debug.c
$ ./test-log-debug
DEBUG 'test-log-debug.c':13: in main()
$
Compiled and tested in VS2013 on Windows 10 again:
DEBUG 'C:\Users\Scheff\tests\test-log-debug.c':13: in main()
visibleman noted that there is a very similar question SO: Visual C++ equivalent of __FILE__ , __LINE__ and __PRETTY_FUNCTION__.
AFAIK, (and also mentioned in one that answers) __FILE__ and __LINE__ are standard. Other/similar macros might be provided as proprietary extension of the compiler.

Defining macro to change print function error due to argument difference

I'm trying to use unity testing framework with an NRF51822 board, but in order to see the output from unity i need to reroute it / pipe so its visible on my coumputer. I am using SEGGER RTT to print in my porject and ideally id use the same for unity.c output.
According to unity
By default, Unity prints its results to stdout as it runs. This
works perfectly fine in most situations where you are using a native
compiler for testing. It works on some simulators as well so long as
they have stdout routed back to the command line. There are times,
however, where the simulator will lack support for dumping results or
you will want to route results elsewhere for other reasons. In these
cases, you should define the UNITY_OUTPUT_CHAR macro. This macro
accepts a single character at a time (as an int, since this is the
parameter type of the standard C putchar function most commonly
used). You may replace this with whatever function call you like.
* Output* - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if
desired
/*-------------------------------------------------------
* Output Method: stdout (DEFAULT)
*-------------------------------------------------------*/
#ifndef UNITY_OUTPUT_CHAR
/* Default to using putchar, which is defined in stdio.h */
#include <stdio.h>
#define UNITY_OUTPUT_CHAR(a) (void)putchar(a)
#else
/* If defined as something else, make sure we declare it here so it's ready for use */
#ifndef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION
extern void UNITY_OUTPUT_CHAR(int);
#endif
#endif
I tried to define
#define UNITY_OUTPUT_CHAR(a) SEGGER_RTT_WriteString(0, a)
However i get the following
> $ make rm -rf _build echo Makefile Makefile mkdir _build Compiling
> file: system_nrf51.c Compiling file: main.c
> C:/NXTSNS/nRF5_SDK_11.0.0_89a8197/examples/peripheral/blinky/main.c:31:53:
> error: expected declaration specifiers or '...' before numeric
> constant
> #define UNITY_OUTPUT_CHAR(a) SEGGER_RTT_WriteString(0, a)
> ^ C:/NXTSNS/Unittesting/unity/src/unity_internals.h:250:13: note: in
> expansion of macro 'UNITY_OUTPUT_CHAR' extern void
> UNITY_OUTPUT_CHAR(int);
> ^ Makefile:150: recipe for target '_build/main.o' failed make: *** [_build/main.o] Error 1
I also tried this alternative of calling segger in a function and casting to char * as follows
void print_test(int a){
SEGGER_RTT_WriteString(0, (char *) a);
}
but unfortuneatly i dont see any output when i call print_test
How should i define the macro such that i can send the output to segger or if there is a more suitable alternative what is it?

Is there any way to get the source code line number in C code in run time? [duplicate]

This question already has answers here:
C/C++ line number
(10 answers)
Closed 6 years ago.
Is there any way to get the source code line number in C code in run time?
The thought behind it is, suppose a software is made in plain C language. the .exe file is distributed to a user who knows nothing about C. Now if there is any error, the user can see the line number and report the error to the manufacturer so that the debugging can be done at manufacturer site. I just to debug the run time errors and get the corresponding line numbers in the source code while running it. I am a beginner in these stuffs.
If you are using the GCC compiler, you can use the Standard Predefined Macro - __LINE__ as a line number placeholder.
The compiler will fill in the line number while compiling.
Eg :-
printf("%d",__LINE__);
Use gdb instead. But I guess it will work:
if(someThingsWrong())
printf("wrong at line number %d in file %s\n", __LINE__, __FILE__);
You can use the built-in macros __LINE__ and __FILE__, which always expand to the current file name and line number.
#include <stdio.h>
int main(int argc, char *argv[])
{
if(argc<2)
{
printf("Error: invalid arguments (%s:%d)\n", __FILE__, __LINE__);
return 0;
}
printf("You said: %s\n", argv[1]);
return 0;
}

How to get the entire string reported by __LINE__

Is it possible to get the entire string on line reported through LINE macro.
Sample code:
#include <stdio.h>
#define LOG(lvl) pLog(lvl, __LINE__, __FILE__)
pLog(const char *str, int line, const char *file)
{
printf("Line [%u]: File [%s]", line, file);
}
int main ()
{
LOG("Hello"
"world");
return 0;
}
The output is: Line [13]: File [macro.c]
Now in a large code base i want to search this file and print the string "Hello world" present at line reported (in this case it is 13)
One way i was thinking is to search for this file first generate the output file with gcc -E do grep for pLog and save their string then grep for LOG in actual code file and save line number match the line number with the line number present in result and then do matching of index and print the string.
As string can be distributed across multiple lines (as in code Hello is in one line and world is in another line) so also need to take care of that.
Is there anyother best and fast way of doing it or gcc provide some option to convert back line and file to actual code
This is very easy to do with Clang. The following command dumps Abstract Syntax Tree (AST) for the file test.c to the file out:
clang -cc1 -ast-dump test.c > out
Looking at the AST in the generated file you can easily find the information you need:
(StringLiteral 0x1376cd8 <line:12:9, line:13:13> 'char [11]' lvalue "Helloworld")))
Clang gives start of the first token of the string (line:12:9), start of the last token of the string (line:13:13) and the full string ("Helloworld").
You can either parse the AST dump or use Clang API to get the same information. If this is not a one time task, I'd go for API since the AST dump format is more likely to change in the future.
All this of course make sense only if you have a reason not to print the string in pLog itself.

Resources