I doubt you'll find a tool like this off-the-shelf. So, you'd need a custom tool. You don't
want to try doing this with some string hacking method (e.g., Perl) because the details of accurately
parsing C and C++ are far beyond what you can reliably do this way. If you don't mind
string hacking damaging your files sometimes, maybe you can get away with this.
My company's DMS Software Reengineering Toolkit could be used to do this reliably modulo a caveat.
DMS is generic engine for parsing, analyzing, and transforming source code using compiler technology parameterized by explicit langauge definitions. DMS has robust langauge definitions for many languages,
including C and C++ in variety of dialects. Using the DMS C or C++ front ends, you can parse the source
code, build compiler data structures called ASTs, carry out analyses over the code, transform the ASTs,
and then regenerate compilable code including comments and all the prepreprocessor directives.
The caveat has to do with parsing source code containing preprocessor directives:
they have to be well-structured [eg. #ifdef #endif needs to nest around other statements just like regular
if, etc. as opposed to being used across a statement boundary. This happens some in C code; much
less in C++ code. Our experience is that if you are willing to modify your C code little bit,
you can make this particular issue go away.
For your specific task, you do pretty much as the answer for Scientific Toolworks described:
- Choose a compilation unit, and parse it using DMS. You have to provide all the same information
you provide the compiler, so it can locate the header files, etc.
- DMS produces an AST for both your compilation unit and for all header files.
- Walk the ASTs to extract the order of declarations in the headers and the compilation unit.
- Restructure the compilation unit tree according to the order derived from 3)
- Prettyprint the resulting compilation unit AST
[A reason to do this with DMS rather than Scientific Toolworks is that DMS is designed to
parse/transform/regenerate code, whereas SciTool IMHO is really only designed to parse
and analyze. DMS provides access to the fine detail required for transformation that
SciTools does not, at least not the last time I looked].
Complications will ensue because of conditionals, macros, namespaces, ... but you'll have decide policy
for resolution. For instance, if a header file has a #if ... #else .... #endif, and declarations
in the then clause have a different order than they do in the else clause, what's the desired order?
What if a function definition is created by a macro in the header? But, all this is what makes
building a real tool, er, fun.
My personal opinion is this seems like rather a lot of work for the effect you are getting. If you
do all of this, how much better will your software engineering process be? We normally use DMS
to check for coding errors, or change the code in ways that people can't (e.g., insert runtime instrumentation
temporarily or AOP-like advice), where its clear that a mechanical engine has payoff.