Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

script to add namespace to c++ files

Tags:

c++

regex

linux

sed

So I've got giant code base that needs to have a namespace added to it. Instead of doing this manually, I thought of using grep, xargs & sed to add the namespace to all source files...

But my skills are not up to par. Ideally

namespace foo 
{

Would be added after all the includes, and '}' added after the #endif in the .h files.

For the .cpp files, adding 'using namespace foo' after all the includes would be sufficient.

I've been messing around with sed, but haven't gotten very far.

Any help would be appreciated. Thanks!

like image 314
anio Avatar asked Oct 31 '11 20:10

anio


2 Answers

This is not an easy task. Things that make it problematic include

  • Stuff that you do not want to place inside your new namespace such as
    • Constructs like language "C" { C-stuff }
    • Forward declarations of classes that are not yours. This gets n-times harder if you are using some external package that also doesn't use namespaces.
  • Even finding where to place the namespace Foo { and the closing '}' can be tough.
    • You do want to enclose forward declarations, except those that don't belong to you.
    • You generally want to enclose anything at file scope that involves a pair of braces -- except for things like language C.
    • Maintenance programmers (if your code has been around long enough) will have done all kinds of bad things to your code. They'll put forward declarations inside classes or functions, between classes and functions, anywhere but the top that makes it is easy for a script.
    • You don't want to double-nest things. It is suprisingly easy to do so.
    • For various reasons some people put what appears to be extraneous stuff at the end of a header. This can be a particularly nasty problem.
    • If you decide to try to enclose each class, struct, and enum you're going to have to figure out where the start of the declaration really is. You want to wrap template declaration, if any, and of course doxygen comments and the like.
    • Finding the end of a class can be just nasty. People have this nasty tendency to put non-matching braces in comments and strings.

Good luck! A script will take a bit more than a half an hour to write. It will take far less time than rewriting all your code. I suggest that you use something a tad more powerful than sed. Perl, python, and ruby are three good choices.

like image 127
David Hammen Avatar answered Oct 12 '22 07:10

David Hammen


This got me half way:

#!/bin/sh
NAMESPACE=my_namespace
for x in $(find . -name "*.h"); do
    sed -i "$(grep -n "^#" $x | tail -2 | head -1 | sed 's/:.*//')a\\\nnamespace $NAMESPACE {\n" $x
    sed -i "$(($(grep -n "^#" $x | tail -1 | sed 's/:.*//')-1))a} // namespace $NAMESPACE\n" $x
done

for x in $(find . -name "*.cpp"); do
    sed -i "$(grep -n "#include" $x | tail -1 | sed 's/:.*//')a\\\nnamespace $NAMESPACE {\n" $x
    echo >> $x
    echo "} // namespace $NAMESPACE" >> $x
done

It mostly locates the one but last preprocessor directive in the h file and adds the namespace there. it colses the namespace right before the last preprocessor directive (I assume that I have an #endif at the end of my h files). If that's not the case, The script can be adapted accordingly.

In the cpp case, I look for the last include to open the namespace and close it at the end of the file.

This is far from perfect, but facing with 100+ files it made the job a lot easier.

like image 33
Shloim Avatar answered Oct 12 '22 09:10

Shloim