einpoklum
einpoklum

Reputation: 132108

How can I tell which defines are missing in a C file, not via compilation failure?

I have a C file (for simplicity, assume it includes nothing). This C files requires several definitions of literal numbers to compile properly - and I want to figure out which definitions these are.

Naturally, one can try to compile the file, and at some point we would start to get failures; with some failure recovery, we might get failure notifications about additional defines. But - that's not what I want:

What are my alternatives for getting the list of undefined macros?

Motivation: In reality, I'm feeding something into a dynamic compilation library, and I want to check beforehand if all necessary macros have been defined, without knowing a priori which macros the file needs (i.e. it could be different ones for different input files).

Upvotes: 1

Views: 52

Answers (2)

Peter - Reinstate Monica
Peter - Reinstate Monica

Reputation: 16057

You could use something around the idea that every identifier-like non-keyword outside a comment in a C file must be declared somewhere. (I think! Is that correct?)

The basic idea is to generate a list of such identifiers and search the program and then the included headers for a declaration of each. While this can be done by hand and ad-hoc it probably makes sense to index all potential header files and to use something like ctags for indexing as well as finding (there is a libctags, as I just learned).

I assume that the solution doesn't have to be perfect — missed cases will simply fail compilation — but that you want to reduce such cases. In that case the parsing of the source code for identifiers does not have to be perfect (it can ignore nested comments etc.) and can probably be done "manually" with acceptable effort.

Upvotes: 0

einpoklum
einpoklum

Reputation: 132108

The ugly fallback solution:

Obviously, your fallback is to just compile the program. But - do so while minimizing irrelevant messages and irrelevant. This will be compiler-dependent, but with GCC for example, you can:

  • Avoid any output generation
  • Suppress warnings
  • Suppress notes
  • Be strictly standard-compliant, no GNU extensions
  • Disable the use of those dumb fancy quotation marks GCC insists on using

... using various command-line switches and when making it take input from the standard input stream rather than a file (only way I've found so far to suppress some of the notes). That looks like:

  cat your_program.c \
|  LC_CTYPE=C gcc -std=c99 -fsyntax-only -x c -fcompare-debug-second -

and the output could look like:

<stdin>: In function 'mult':
<stdin>:3:18: error: 'MY_CONSTANT' undeclared (first use in this function)

Now, if your program is correct other than the undefined macros (= undeclared identifiers), then you can easily parse the above with a bit of shell scripting:

  cat your_program.c \
| LC_CTYPE=C gcc -std=c99 -fsyntax-only -x c -fcompare-debug-second - \
| sed -r '/error: /!d; s/^.*error: '"'//; s/'.*//;" \
| sort -u

This has the further disadvantage of not being fully embeddable into your program, i.e. you can't invoke the partial compilation using some library in some program of yours, then programmatically parse the output. You would need a system()-type call.

Note: If your program can have other errors, the pattern for dropping the line in the sed command will need to be a little more specific.

Upvotes: 1

Related Questions