Phillip Hamnett
Phillip Hamnett

Reputation: 298

Generate a list of existing functions across multiple files in C

Due to paperwork that has to be filled out, I need to know how many functions exist in an entire C project.

The project is split across multiple folders, so ideally what I am looking for is something where you can type in:

FindAllTheFunctions --recursive /path/to/folder

And the result is written something like:

/path.../filename: int foo(float bar)
.
.
.
/path.../final/filename: double foo2(int bar2)

How could I get results of this nature?

Many thanks!

Upvotes: 0

Views: 1353

Answers (3)

Masatake YAMATO
Masatake YAMATO

Reputation: 1300

The cross reference feature of ctags may help you.

  1. Install Universal-ctags (https://ctags.io)
  2. Run find $dir --name '*.c' | ctags --kinds-C=f -x --_xformat='%F: %{C.properties} %t %N%S'
$ find ./main -name '*.c' | ./ctags --kinds-C=f -x --_xformat='%F: %{C.properties} %t %N%S' -L - | head
./main/args.c: extern Arguments * argNewFromArgv(char * const * const argv)
./main/args.c: extern Arguments * argNewFromFile(FILE * const fp)
./main/args.c: extern Arguments * argNewFromLineFile(FILE * const fp)
./main/args.c: extern Arguments * argNewFromString(const char * const string)
./main/args.c: extern bool argOff(const Arguments * const current)
./main/args.c: extern char * argItem(const Arguments * const current)
./main/args.c: extern void argDelete(Arguments * const current)
./main/args.c: extern void argForth(Arguments * const current)
./main/args.c: extern void argSetLineMode(Arguments * const current)
./main/args.c: extern void argSetWordMode(Arguments * const current)

Upvotes: 0

Matteo Italia
Matteo Italia

Reputation: 126877

Moving/expanding from the comments, a slightly more general one-liner:

ctags -f - -R | cut -s -f 4- | grep -P '(^|\t)f($|\t)' | wc -l
  1. ctags -R parses (... mostly...) recursively the supported files in the current directory; -f - redirects its output to stdout instead of writing a tags file;
  2. we use cut to only extract the fields we are interested in;

    The tags file format is made of fields separated by tabs (so the default delimiters for cut are already ok); the first three fields have a fixed meaning and are not of our interest, while the ones that follow are "extended fields", where we are looking for a single f that indicates that the row refers to a function.

    -s matches only lines with delimiters (= skip garbage); -f 4- outputs only from the fourth field to the last.

  3. we use grep to look for our lonely f; the order of "extended fields" is not guaranteed - and in facts, when calling ctags over a C++ project I saw that extra fields besides f are added (class: fields in particular).

    -P uses PCRE regexes (just because it's easier to look for a tab character, egrep would suffice otherwise); (^|\t)f($|\t) looks for an f either surrounded by our separators (tabs) or by the start/end of line;

  4. wc -l counts the resulting lines; the result should be the number of function definitions.

Upvotes: 2

Phillip Hamnett
Phillip Hamnett

Reputation: 298

Thanks everyone for all of your useful comments!

In the end, this is what I did: I created the tags file using ctags:

ctags --recurse=yes path/to/base/of/code

This generates an output file called tags

I use vim as a text editor. So I opened the tags file and typed:

:v/f$/d

Which searches for all lines in the file that don't end with f and deletes them.

What I was left with were all of the functions from the code. How many functions?

wc -l tags

It is only 535 functions, now I have to document them all...

Upvotes: 2

Related Questions