0

Sort of similar to this question, I need to print all printf's inside multiple c files. The printf's can be multilined, and there can be multiple printf's per file. I'd prefer to not print any leading/trailing comments on the line... So for example, If I have the following file:

// do not print this
rc = printf("blah");

//do not print this
rc = printf("a multiline printf %d %d",
    1, 2);
//do not print this

Should output:

printf("blah");
printf("a multiline printf %d %d",
    1, 2);

I'll assume that the printf does not have any ; character in the format string, thus this would be -- find printf string, print until ; found, repeat... Is there a simple way to do this in awk/sed?

HardcoreHenry
  • 5,909
  • 2
  • 19
  • 44
  • Should a line like `char *str = "we like using printf(foo);"` be printed? How about a line like `x = 7; // later we will do printf(bar);`? – Ed Morton Apr 06 '21 at 15:18
  • I don't mind these showing up in the results (these will be few and far between). This is part of a larger effort to find misuse of some format specifiers, so false negatives won't cost me much time – HardcoreHenry Apr 06 '21 at 15:25
  • @Barmar -- I thought that by adding a link to other SO questions, it would be obvious I did try other things. However those things didn't work, and so I didn't feel they added any benefit to the question. – HardcoreHenry Apr 06 '21 at 17:14
  • 1
    Those things didn't work because they're solving different problems. So you need to write a solution to your problem, perhaps using what you found in those questions as a starting point. Then you post what you came up with, and we help you fix it. – Barmar Apr 06 '21 at 17:16
  • Programming isn't "paint by numbers", you can't always expect to find a pre-written solution to your problem. You need to do your own coding. – Barmar Apr 06 '21 at 17:17
  • This is kind of an interesting point. I had tried some basic attempts using sed and awk, none of which worked, so I then searched the web. I did find similar issues, but not an exact match, so I posted here in the hopes that an expert could point me to the correct approach (which they did). So technically, my question wasn't one of 'why doesn't this code work' as it was not hard to discern why they failed. This was more a gap in my knowledge of how to implement what I needed (note that the question does have pseudo code of what I was trying to do). Do you consider this off topic? – HardcoreHenry Apr 06 '21 at 17:38

1 Answers1

1

With GNU tools:

$ awk -v RS='printf[(][^;]+;' 'RT{print RT}' file
printf("blah");
printf("a multiline printf %d %d",
    1, 2);

$ grep -zEo 'printf[(][^;]+;' file | tr '\0' '\n'
printf("blah");
printf("a multiline printf %d %d",
    1, 2);

The main difference between the 2 is that the grep solution will read the whole input file into memory while the awk solution will just read one printf-separated record at a time.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • Maybe preprocess to handle odd C code slightly better? `cpp -D'printf(...)=__RS__PRINTF(__VA_ARGS__)__RS__' file.c | awk -v RS=__RS__ '/^PRINTF/{sub(/PRINTF/,"printf");print}'` (but need to choose suitably unique RS) – jhnc Apr 06 '21 at 15:50
  • Yeah, a robust solution would need a C parser (e.g. see https://stackoverflow.com/a/13062682/1745001, https://stackoverflow.com/a/35708616/1745001, https://stackoverflow.com/a/34936725/1745001 and https://stackoverflow.com/a/56399647/1745001 for answers to somewhat similar types of question) but [the OP said](https://stackoverflow.com/questions/66971348/awk-sed-print-all-printfs-inside-of-c-file/66971703?noredirect=1#comment118381248_66971348) they don't care about false matches and so neither do I :-). – Ed Morton Apr 06 '21 at 16:01
  • 1
    Yes, thanks. I need a best effort approach. The awk command works like a charm. I had to look up what RS and RT did, but now that I know, I can tweak as needed. Appreciate the help. – HardcoreHenry Apr 06 '21 at 16:44