blog dds

2005.02.07

Macro-based Substitutions in Source Code

A friends asks: "How can one easily replace a method call (which can contain arguments with brackets in its invocation code) with a simple field access?

For example, we might want to substitute

p->getname(a, strlen(a))
with
p->name

It is not possible to use a regular expression in our editor, because we can't account for the nested brackets in the method call's arguments. It turns out that a simple pipeline involving sed and the C preprocessor cpp will do the job for us. The trick is to hide the other C preprocessor commands, instruct the preprocessor to pass comments unchanged, and not emmit #line directives. The following Unix command will do the trick:

sed 's/#/^A/g;s/\\/^B/g;1i\
#define getname(a, b) name' oldfile.c |
cpp -P -C |
sed 's/^A/#/g;s/^B/\\/g' >newfile.c
The sequence ^A above is a control-A character.

We also can use the same idea to:

  • change the order of a function's arguments, or
  • add or remove arguments to a function.
The same command also works for Java programs

However, the substitution takes place at the program's lexical level, and does not take into account types and scope. For that we need a more powerful tool, like CScout (in the case of C code), or the refactoring capabilities of Eclipse (in the case of Java code).

Read and post comments, or share through   


Creative Commons License Last modified: Tuesday, February 8, 2005 1:50 pm
Unless otherwise expressly stated, all original material on this page created by Diomidis Spinellis is licensed under a Creative Commons Attribution-Share Alike 3.0 Greece License.