What are you trying to accomplish by doing this? Based on the description of the task, there is probably a much easier way to approach the problem. If you're sure that this is the best way to accomplish your task, read on.
You would have to implement some sort of rudimentary C language parser to do this. Since you are processing text, I would recommend using a scripting language like perl, python, or ruby to modify your text instead of writing a C program to do it.
Your parser will walk through the file a line at a time and for each line, it will determine whether it needs to insert your macro. The parser will need to keep track of a number of things. First, it needs to keep track of whether or not it is currently inside of a comment. When you encounter a /*
sequence, set a "in comment" flag and clear it the next time you encounter a */
sequence. Whenever that flag is set, you will not add a macro invocation. Also, you will need to keep track of whether or not you are inside a function. Assuming your code is fairly simple and straightforward, you can have a "brace counter" that starts at zero, increments whenever you encounter a {
, and decrements whenever you encounter a }
. If your brace counter is zero, then you are not inside of a function and you shouldn't add a macro call. You will also want to add special code to detect and ignore braces that are part of a structure definition, array initializer, etc. Note that simple brace counting won't work if your code does more complicated things like:
void some_function (int arg) {
#ifdef CHECK_LIMIT_ONLY
if (arg == 0) {
#else
if (arg < 10) {
#endif
// some code here
...
}
}
While you could argue that snippet is simply a case of poorly-written code, it's just an example of the type of problem that you can run into. If your code has something in it that breaks simple brace counting, then this problem just got significantly more difficult. One way to tell if your code will break brace counting is if you reach the end of the file with a non-zero brace count or if at any point in time the brace count goes negative.
Once you can determine when you are in a function and not in a comment, you need to determine whether the line needs a macro inserted after it. You can start with a few simple rules, test the script, and see if there are any cases that it missed. For starters, any line ending in a semicolon is the end of a statement and you will want to insert a macro after it. Similar to counting braces, when you are inside of a function you will want to count parenthesis so that you can determine if you are inside of a function call, loop conditional, or other compound statement. If you are inside one of these, you will not add the macro. The other code location to track is the the start and end lines of a { ... }
block. If a line ends in {
or }
, you will add a macro after it.
For a complicated task like this, you will definitely want to script something up, try it out on a relatively simple piece of code, and see what it gets wrong. Make adjustments to cover the cases you missed the first time and re-test. When it can parse the simple code correctly, give it something more complicated and see how well it does.
''Update:'' To address the concerns that some people have expressed regarding the additional latency of adding print commands, remember that you don't have to print a timestamp at every macro call. Instead, have the macro call grab a timestamp and stick it onto a list. Once your program is done, print all the timestamps off of the list. That way, you save all the print-related delay until after your test is over.