<?xml version="1.0" ?>
<notes>
The nature of the C language and its preprocessor can result in pathological 
cases that can confuse the <em>CScout</em> analysis and substitution engine.
In all cases the confusion only results in erroneous analysis or 
substitutions of the particular identifiers and will not affect other
parts of the code.
In some cases you can even slightly modify your workspace definition
or code to ensure <em>CScout</em> works as you intend.
The following cases are the most important in recognising and substituting
identifiers:

<ol>
<li> Conditional compilation<p>
Some programs have parts of them compiled under conditional preprocessor
directives.
Consider the following example:

<fmtcode ext="c">
#ifdef unix
#include <unistd.h>
#define erase_file(x) unlink(x)
#endif

#ifdef WIN32
#include <windows.h>
#define erase_file(x) DeleteFile(x)
#endif

main(int argc, char *argv[])
{
	erase_file(argv[1]);
}
</fmtcode>

As humans we can understand that <code>erase_file</code> occurs three times
within the file.
However, because <em>CScout</em> preprocesses the file following the 
C preprocessor semantics, it will typically match only two instances.
In some cases you can get around this problem by defining macros that will
ensure that all code inside conditional directives gets processed.
In other cases this will result in errors (e.g. a duplicate macro definition
in the above example).
In such cases you can include in your workspace the same project multiple
times, each time with a different set of defined macros.
<pre>
workspace example {
	project idtest {
		define DEBUG 1
		define TEST 1
		file idtest.c util.c
	}
	project idtest2 {
		define NDEBUG 1
		define PRODUCTION
		file idtest.c util.c
}
</pre>
<li> Partial coverage of macro use <p>
Consider the following example:
<fmtcode ext="c">
struct s1 {
	int id;
} a;

struct s2 {
	char id;
} b;

struct s3 {
	double id;
} c;

#define getid(x) ((x)->id)

main()
{
	printf("%d %c", getid(a), getid(b));
}
</fmtcode>
In the above example, changing an <code>id</code> instance should
also change the other three instances.
However, <em>CScout</em> will not associate the member of 
<code>s3</code> with the identifier appearing in the <code>getid</code>
macro or the 
<code>s1</code> or <code>s2</code> structures, 
because there is no <code>getid</code> macro invocation to link them together.
If e.g. <code>id</code> is replaced with <code>val</code>
the program will compile and function correctly,
but when one tries to access the <code>c</code> struture's member
in the future using <code>getid</code> an error will result.

<fmtcode ext="c">
struct s1 {
	int val;
} a;

struct s2 {
	char val;
} b;

struct s3 {
	double id;
} c;

#define getid(x) ((x)->val)

main()
{
	printf("%d %c", getid(a), getid(b));	/* OK */
	printf(" %g", getid(c));		/* New statement: error */
}
</fmtcode>

To avoid this (rare) problem you can introduce dummy macro invocations
of the form:

<fmtcode ext="c">
#ifdef CSCOUT
	(void)getid(d)
#endif
</fmtcode>


<li> Undefined macros<p>
We employ a heuristic classifying all instances of an undefined macro
as being the same identifier.
Thus in the following sequence <code>foo</code> will match all
three macro instances:
<fmtcode ext="c">
#undef foo

#ifdef foo
#endif

#ifdef foo
#endif

#define foo 1
</fmtcode>
In most cases this is what you want, but there may be cases where the macro
appears in different files and with a different meaning.
In such cases the undefined instances of the macro will erroneously
match the defined instance.
</ol>
<p>
In addition, the analysis of functions can be confused by the following
situations.
<ol>
<li> Functions getting called through function pointers will not
appear in the call graphs.
This is a common limitation of static call analysis.</li>
<li> Function-like macros called from inside function bodies that
were generated by macro expansion will not be registered as calls.</li>
<li> Non-function like macros that expand into function calls will
not appear in the call graph; the corresponding functions will appear
to be called by the function containing the macro.</li>
</ol>
<p>
Finally, because function argument refactoring works at a higher level
thann simple identifiers, the following limitations hold.
<ol>
<li>When a function call's arguments macro-expand into unballanced brackets
or into multiple function arguments the replacement can misbehave.</li>
<li>When there is not a one-to-one correspondence between a
function's name and its associated identifier
(i.e. when the function's name is generated through macro-token concatenation)
the function argument refactoring is not offered as an option.
</li>
</ol>
</notes>
