1<?xml version="1.0" ?>
2<notes>
3The nature of the C language and its preprocessor can result in pathological
4cases that can confuse the <em>CScout</em> analysis and substitution engine.
5In all cases the confusion only results in erroneous analysis or
6substitutions of the particular identifiers and will not affect other
7parts of the code.
8In some cases you can even slightly modify your workspace definition
9or code to ensure <em>CScout</em> works as you intend.
10The following cases are the most important in recognising and substituting
11identifiers:
12
13<ol>
14<li> Conditional compilation<p>
15Some programs have parts of them compiled under conditional preprocessor
16directives.
17Consider the following example:
18
19<fmtcode ext="c">
20#ifdef unix
21#include <unistd.h>
22#define erase_file(x) unlink(x)
23#endif
24
25#ifdef WIN32
26#include <windows.h>
27#define erase_file(x) DeleteFile(x)
28#endif
29
30main(int argc, char *argv[])
31{
32	erase_file(argv[1]);
33}
34</fmtcode>
35
36As humans we can understand that <code>erase_file</code> occurs three times
37within the file.
38However, because <em>CScout</em> preprocesses the file following the
39C preprocessor semantics, it will typically match only two instances.
40In some cases you can get around this problem by defining macros that will
41ensure that all code inside conditional directives gets processed.
42In other cases this will result in errors (e.g. a duplicate macro definition
43in the above example).
44In such cases you can include in your workspace the same project multiple
45times, each time with a different set of defined macros.
46<pre>
47workspace example {
48	project idtest {
49		define DEBUG 1
50		define TEST 1
51		file idtest.c util.c
52	}
53	project idtest2 {
54		define NDEBUG 1
55		define PRODUCTION
56		file idtest.c util.c
57}
58</pre>
59<li> Partial coverage of macro use <p>
60Consider the following example:
61<fmtcode ext="c">
62struct s1 {
63	int id;
64} a;
65
66struct s2 {
67	char id;
68} b;
69
70struct s3 {
71	double id;
72} c;
73
74#define getid(x) ((x)->id)
75
76main()
77{
78	printf("%d %c", getid(a), getid(b));
79}
80</fmtcode>
81In the above example, changing an <code>id</code> instance should
82also change the other three instances.
83However, <em>CScout</em> will not associate the member of
84<code>s3</code> with the identifier appearing in the <code>getid</code>
85macro or the
86<code>s1</code> or <code>s2</code> structures,
87because there is no <code>getid</code> macro invocation to link them together.
88If e.g. <code>id</code> is replaced with <code>val</code>
89the program will compile and function correctly,
90but when one tries to access the <code>c</code> struture's member
91in the future using <code>getid</code> an error will result.
92
93<fmtcode ext="c">
94struct s1 {
95	int val;
96} a;
97
98struct s2 {
99	char val;
100} b;
101
102struct s3 {
103	double id;
104} c;
105
106#define getid(x) ((x)->val)
107
108main()
109{
110	printf("%d %c", getid(a), getid(b));	/* OK */
111	printf(" %g", getid(c));		/* New statement: error */
112}
113</fmtcode>
114
115To avoid this (rare) problem you can introduce dummy macro invocations
116of the form:
117
118<fmtcode ext="c">
119#ifdef CSCOUT
120	(void)getid(d)
121#endif
122</fmtcode>
123
124
125<li> Undefined macros<p>
126We employ a heuristic classifying all instances of an undefined macro
127as being the same identifier.
128Thus in the following sequence <code>foo</code> will match all
129three macro instances:
130<fmtcode ext="c">
131#undef foo
132
133#ifdef foo
134#endif
135
136#ifdef foo
137#endif
138
139#define foo 1
140</fmtcode>
141In most cases this is what you want, but there may be cases where the macro
142appears in different files and with a different meaning.
143In such cases the undefined instances of the macro will erroneously
144match the defined instance.
145</ol>
146<p>
147In addition, the analysis of functions can be confused by the following
148situations.
149<ol>
150<li> Functions getting called through function pointers will not
151appear in the call graphs.
152This is a common limitation of static call analysis.</li>
153<li> Function-like macros called from inside function bodies that
154were generated by macro expansion will not be registered as calls.</li>
155<li> Non-function like macros that expand into function calls will
156not appear in the call graph; the corresponding functions will appear
157to be called by the function containing the macro.</li>
158</ol>
159<p>
160Finally, because function argument refactoring works at a higher level
161thann simple identifiers, the following limitations hold.
162<ol>
163<li>When a function call's arguments macro-expand into unballanced brackets
164or into multiple function arguments the replacement can misbehave.</li>
165<li>When there is not a one-to-one correspondence between a
166function's name and its associated identifier
167(i.e. when the function's name is generated through macro-token concatenation)
168the function argument refactoring is not offered as an option.
169</li>
170</ol>
171</notes>
172