Ctags pinches source file with unbalanced curly braces due to #ifdef

I use ctags to generate the tags file for the C project I'm working on, but many functions are missing from the file. This is apparently caused by unbalanced curly braces in the source files due to the use of #ifdef . A (simplified):

 #include <stdio.h> struct mystruct { long member; #ifndef _MSC_VER }__attribute__ ((packed)); #else /* _MSC_VER */ }; #pragma pack(pop) #endif /* _MSC_VER */ char* greeting_text(){ return "Hello world\n"; } int main( int argc, const char* argv[] ){ char * greeting = greeting_text(); printf(greeting); return 0; } 

This compiles and works flawlessly with gcc -Wall under Linux. However, if I analyze it using ctags problem.c , the tags file contains only entries for mystruct - there are no functions.

ctags --verbose reports:

 OPENING problem.c as C language file problem.c: unexpected closing brace at line 8 problem.c: retrying file with fallback brace matching algorithm OPENING problem.c as C language file problem.c: unexpected closing brace at line 8 

therefore, obviously, ctags does not like preprocessor tricks in a file.

Is there a way to make ctags handle this?

The manpage ctags even explicitly mentions this problem, but indicates that ctags can get around this. However, this does not work ...

This is with Exuberant Ctags 5.8 (Debian package 1: 5.8-4).

Edit:

I am also interested in alternatives to ctags that handle these types of constructs.

+2
source share
4 answers

Due to problems with ctags, I ended up using cscope .

While not perfect, it handles macros better than ctags, and can integrate with vim, like ctags (see http://vimdoc.sourceforge.net/htmldoc/if_cscop.html#:cscope ).

+2
source

I tried to run the preprocessor ( gcc -E ) in the files before giving them ctags. Whether this will be a good result, I'm not sure, but it's worth a try. Of course, then all the components of your code should appear, but will ctags recognize the links of other files that gcc leaves in the output? Not sure.

+1
source

You can try rewriting the code so that there is only one closing curly bracket, for example:

 struct mystruct { long member; } #ifndef _MSC_VER __attribute__ ((packed)) #endif ; #ifdef _MSC_VER #pragma pack(pop) #endif /* _MSC_VER */ 

Of course, you can define some convenience macros to make them easier to read.

+1
source

You can run the unifdef tool to selectively (and temporarily) replace the inactive part of the code with empty lines (unifdef -l -U_MSC_VER) . The result is

 #include <stdio.h> struct mystruct { long member; }__attribute__ ((packed)); char* greeting_text(){ return "Hello world\n"; } int main( int argc, const char* argv[] ){ char * greeting = greeting_text(); printf(greeting); return 0; } 

Ctags has no problems with parsing and line numbers remain unchanged (important if you create a ctags search by line number):

 $ cat tags !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ !_TAG_PROGRAM_AUTHOR Darren Hiebert / dhiebert@users.sourceforge.net / !_TAG_PROGRAM_NAME Exuberant Ctags // !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ !_TAG_PROGRAM_VERSION 5.6 // greeting_text yc /^char* greeting_text(){$/;" f main yc /^int main( int argc, const char* argv[] ){$/;" f member yc /^ long member;$/;" m struct:mystruct file: mystruct yc /^struct mystruct {$/;" s file: 

unifdef is available in many operating systems as a package (for example, FreeBSD, various Linux distributions, Cygwin). Homepage: http://dotat.at/prog/unifdef/

+1
source

Source: https://habr.com/ru/post/1384167/


All Articles