DevNull DevNull - 3 months ago 11
C Question

Strip all instances of specific function(s) from C source

Background



I have a test application that involves libraries from several separate contractors. Each contractor writes a library that utilizes a common logging API which I have already provided. At build time, I can pass a flag which optimizes the logging calls out entirely, as they are pre-processor macros which wrap our underlying
fprintf()
wrapper.

A product requirement change now mandates that two of the contractors can see each others code bases in a limited manner.




The Problem



The logging statements for some of the code the separate contracted teams use has to be purged from code before it is shared between teams, as it may contain intellectual property that we aren't licensed to shared between teams (ie: an explanation of how some obscure algorithm works).




The Question



How can I, on Linux (using
BASh
,
sed
,
VIM
,
awk
, etc), strip all instances of a certain function from source. Some samples:

logToClient("Something wrong with process %s (owner = %d).\n",
pName, iOwner);

logToClientVerbose("Big problem.");


I've tried writing a little python script to create a "stack" of all the
(
and
)
characters encountered, but it doesn't work 100% of the time, and I'm hoping there's a simply piece of regex one-liner magic that can accomplish this.

Thank you.

Answer

Consider this test file:

$ cat file.c
logToClient2("keep this");
logToClient("Something wrong with process %s (owner = %d).\n", pName, iOwner);
logToClientVerbose("Big problem.");
logToClientVerb("Keep Verb.");

To delete all references to the two functions that you want deleted:

$ grep -vwE 'logToClient|logToClientVerbose' file.c
logToClient2("keep this");
logToClientVerb("Keep Verb.");

How it works:

  • -v tells grep to delete lines that match.

  • -w tells grep to match only on whole words.

  • -E tells grep to used extended regular expressions: this is so that we don't have to escape |.

  • logToClient|logToClientVerbose matches either logToClient or logToClientVerbose.

Limitation: This does not parse C. This only deletes lines with matching words.

Commands spread over multiple lines

Consider this test file:

$ cat file2.c
logToClient2("keep this");
logToClient("Something wrong with process %s (owner = %d).\n", 
      pName, iOwner);
logToClientVerbose("Big problem.");
logToClientVerb("Keep Verb.");

This awk command divides up the file into records that are marked by a record separator of a semicolon followed by a newline. It deletes all such records that match one of the words logToClient or logToClientVerbose:

$ awk '!/\<(logToClient|logToClientVerbose)\>/' RS=';\n' ORS=';\n' file2.c
logToClient2("keep this");
logToClientVerb("Keep Verb.");

Limitation: This does not parse C. This only deletes records with matching words. For example, this will be confused by multiple commands on one line or by lines with spaces after semicolons.