28

I want to do this:

extract_prototypes file1.c file2.cpp file3.c

and have whatever script/program print a nice list of function prototypes for all functions defined in the given C / C++ files. It must handle multi-line declarations nicely.

Is there a program that can do this job? The simpler the better.

EDIT: after trying to compile two C programs, bonus points for something that uses {perl, python, ruby}.

Peter
  • 127,331
  • 53
  • 180
  • 211

11 Answers11

39

I use ctags

# p = function declaration, f = function definition
ctags -x --c-kinds=fp /usr/include/hal/libhal.h

Also works with C++

ctags -x --c++-kinds=pf --language-force=c++ /usr/include/c++/4.4.1/bits/deque.tcc

Note, you may need to add include paths, do this using the -I /path/to/includes.

ideasman42
  • 42,413
  • 44
  • 197
  • 320
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • A pity that you will need to filter the result. Otherwise it would have being perfect. The result is in form of – rxantos Nov 26 '14 at 20:22
  • When I use try this I get the error "ctags: unrocognized option '--c-kinds=fp'. I am using ctags.exe on windows. Any idea on why I get this error? – mashrur Feb 18 '16 at 16:44
  • 1
    This only works if the declarations are not broken over many lines, at least with Exuberant Ctags 5.8. – mondaugen Nov 22 '17 at 18:13
15

The tool cproto does what you want and allows to tune the output to your requirements.

Note: This tool also only works for C files.

Frank Bollack
  • 24,478
  • 5
  • 49
  • 58
  • argh, having trouble compiling stuff tonight it seems (on mac). looks good though... – Peter Oct 15 '09 at 08:14
  • 2
    Not a standalone tool. It needs gcc to be installed (tried on windows). – rxantos Nov 26 '14 at 20:19
  • 1
    Note that cproto no longer works correctly on gcc 4.5 or later, due to a change in how gcc handles missing header files. (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55115) – Haydentech Jul 25 '17 at 20:53
4

I use ctags and jq

ctags --output-format=json --totals=no --extras=-F --fields=nP file1.c |
jq -sr 'sort_by(.line) | .[].pattern | ltrimstr("/^") | rtrimstr("$/") | . + ";"'
Steve Ward
  • 486
  • 4
  • 11
3

If you have universal-ctags (https://ctags.io), --_xformat option may be useful though you need sed and tr commands to get what you want.

$ cat input.c 
struct object *new_object (struct
                           /* COMMENT */
                           param
                           /* IGNORE ME */
                           *p)
{
    return NULL;
}
int main (void)
{
    return 0;
}
$ ./ctags -o - --kinds-C=f --kinds-C++=f -x --_xformat='%{typeref} %{name} %{signature};' input.c | tr ':' ' ' | sed -e 's/^typename //'
struct object * new_object (struct param * p);
int main (void);
$

This is similar to the answer posted by Steve Ward but this one requires sed, and tr instead of jq.

Masatake YAMATO
  • 1,210
  • 9
  • 10
2

http://cfunctions.sourceforge.net

(This only does C and a limited subset of C++. Disclaimer: this is my program.)

  • here's a slightly more useful piece of information, in case it helps... http://pastie.org/655762 – Peter Oct 15 '09 at 08:29
  • Thanks. I've fixed that bug & have uploaded a new version to sourceforge. I'm having trouble with the administration interface of sourceforge so I'm not sure whether it will be the default download. However, the files should be there. –  Oct 15 '09 at 08:50
  • The new version seems to be showing up on sourceforge now. If you have the time and patience left to try it out again, please let me know if you find any more problems. Google group is http://groups.google.com/group/cfunctions –  Oct 15 '09 at 13:26
  • still couldn't get it working much at all with c++, unfortunately. – Peter Oct 18 '09 at 23:17
  • This project seems to be dead. Does anybody know where to find it? – kvantour Mar 11 '19 at 10:58
1

I used to use doxygen to generate documentation for my C++ code. I am not an expert, but i think you can use doxygen to generate some sort of index file of the function prototypes.

Here is a thread of someone asking a similar question

Andrew Keith
  • 7,515
  • 1
  • 25
  • 41
1

If you format your comments suitably, you could try DOxygen. In fact, if you've not tried it before I'd recommend giving it a go anyway - it will produce inheritance graphs as well as full member function lists and descriptions (from your comments).

albert
  • 8,285
  • 3
  • 19
  • 32
Jon Cage
  • 36,366
  • 38
  • 137
  • 215
  • yeah, been down the doxygen path and I'm after something much simpler for this one task. (I'll leave the discussion about the merits of doxygen to another thread.) – Peter Oct 15 '09 at 08:12
  • You don't actually have to comment anything. Just make sure your Doxyfile has the option for generating documentation for all members turned on. But agreed, this is quite complicated work, although IIRC there's an XML output option that you could try parsing. – blwy10 Oct 15 '09 at 13:38
1

gccxml is interesting, but it print a xml tree. You need to extract information about class, functions, types, and even the specialized templates of class and functions. gccxml use parser of GCC, so you don't need to do the worst job wich is parsing C++ file, and you are 100% sure that it's what probably the best compilator understand.

Arpegius
  • 5,817
  • 38
  • 53
1

In more modern versions of GCC, you can also use -aux-info to get this information when writing C code. See here.

Here's a sample of what the output looks like:

/* src/main.c:30:NC */ static void usage (const char *);
/* src/main.c:32:NF */ extern int main (int argc, char **argv); /* (argc, argv) int argc; char **argv; */
/* src/main.c:57:NF */ static void usage (const char *prog_name); /* (prog_name) const char *prog_name; */
Mitchell
  • 366
  • 3
  • 9
0

gcc-xml might help, although as it is, it only does half the job you want. You'll need some processing of the XML output

sbk
  • 9,212
  • 4
  • 32
  • 40
  • [rbgccxml](https://github.com/jasonroelofs/rbgccxml) seems to do the rest. It uses another ruby gem called nokogiri to parse the XML. – Sundar Jun 09 '15 at 16:44
0

You can run the source file through this program:

/* cproto_parser.c */
#include <stdio.h>                           
int main (void)                              
{                                            
    int c;                                   
    int infundef = 0;                        
    int nb = 0,                              
        np = 0;                              
    while((c=getc(stdin))!=EOF){             
        if(c=='{'){                          
            if((np==0)&&(nb==0)){infundef=1;}
            nb++;                            
        }                                    
        if (infundef==0) {putc(c,stdout);}   
        if(c=='}'){                          
            if((np==0)&&(nb==1)){infundef=0;}
            nb--;                            
        }                                    
        if(c=='('){np++;}                    
        if(c==')'){np--;}                    
    }                                        
    return 0;                                
}                    

Run through the preprocessor to get rid of comments. If you have unmatched braces due to #ifdefs you have to set defines, include files to make it not so.

e.g., cc cproto_parser.c -o cproto_parser; cc -E your_source_file.c|./cproto_parser

mondaugen
  • 425
  • 5
  • 12