Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to verify external symbols in an .h file to the .c file?

Tags:

c

header-files

In C it is an idiomatic pattern to have your .h file contain declarations of the externally visible symbols in the corresponding .c file. The purpose if this is to support a kind of "module & interface" thinking, e.g enabling a cleaner structure.

In a big legacy C system I'm working on it is not uncommon that functions are declared in the wrong header files probably after moving a function to another module, since it still compiles, links and runs, but that makes the modules less explicit in their interfaces and indicates wrong dependencies.

Is there a way to verify / confirm / guarantee that the .h file has all the external symbols from .c and no external symbols that are not there?

E.g. if I have the following files

module.c

int func1(void) {}
bool func2(int c) {}
static int func3(void) {}

module.h

extern int func1(void);
extern bool func4(char *v);

I want to be pointed to the fact that func4 is not an external visible symbol in module.c and that func2 is missing.

Modern compilers give some assistance in as so much that they can detect a missing declaration that you actually referenced, but it does not care from which file it comes.

What are my options, other than going over each pair manually, to obtain this information?

like image 845
thoni56 Avatar asked Oct 28 '25 07:10

thoni56


1 Answers

I want to be pointed to the fact that func4 is not an external visible symbol in module.c and that func2 is missing.

Using POSIX-ish linux with bash, diff and ctags and given really simple example of input files, you could do this:

$ #recreate input
$ cat <<EOF >module.c
int func1(void) {}
bool func2(int c) {}
static int func3(void) {}
EOF
$ cat <<EOF >module.h
extern int func1(void);
extern bool func4(char *v);
EOF
$ # helper function for extracting only non-static function declarations
$ f() { ctags -x --c-kinds=fp "$@" | grep -v static | cut -d' ' -f1; }
$ # simply a diff
$ diff <(f module.c) <(f module.h)
2,3c2
< func2
---
> func4
$ diff <(f module.c) <(f module.h) |
> grep '^<\|^>' |
> sed -E 's/> (.*)/I would like to point the fact that \1 is not externally visible symbol/; s/< (.*)/\1 is missing/'
func2 is missing
I would like to point the fact that func4 is not externally visible symbol

This will break if for example static keyword is not on the same line as function identifier is introduced, because ctags will not output it them. So the real job of this is getting the list of externally visible function declarations. This is not an easy task and writing such tool is left to others : )

like image 176
KamilCuk Avatar answered Oct 29 '25 22:10

KamilCuk