coan  6.0.1
A C/C++ Configuration Analyzer
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
if_control.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2004, 2006 Symbian Software Ltd. *
3  * All rights reserved. *
4  * Copyright (C) 2002, 2003 Tony Finch <dot@dotat.at>. *
5  * All rights reserved. *
6  * Copyright (C) 1985, 1993 The Regents of the University of California. *
7  * All rights reserved. *
8  * Copyright (C) 2007-2013 Mike Kinghan, imk@burroingroingjoing.com *
9  * All rights reserved. *
10  * *
11  * Contributed by Mike Kinghan, imk@burroingroingjoing.com, *
12  * derived from the code of Tony Finch *
13  * *
14  * Redistribution and use in source and binary forms, with or without *
15  * modification, are permitted provided that the following conditions *
16  * are met: *
17  * *
18  * Redistributions of source code must retain the above copyright *
19  * notice, this list of conditions and the following disclaimer. *
20  * *
21  * Redistributions in binary form must reproduce the above copyright *
22  * notice, this list of conditions and the following disclaimer in the *
23  * documentation and/or other materials provided with the distribution. *
24  * *
25  * Neither the name of Symbian Software Ltd. nor the names of its *
26  * contributors may be used to endorse or promote products derived from *
27  * this software without specific prior written permission. *
28  * *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
32  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *
33  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *
34  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *
35  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS *
36  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED *
37  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,*
38  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF *
39  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
40  * DAMAGE. *
41  * *
42  **************************************************************************/
43 
44 #include "if_control.h"
45 #include "diagnostic.h"
46 #include "line_despatch.h"
47 #include "chew.h"
48 #include "io.h"
49 
53 if_control::if_state if_control::ifstate[MAXDEPTH] = {if_state(0)};
54 size_t if_control::depth = 0;
55 size_t if_control::if_start_lines[MAXDEPTH] = {0};
56 
58 {
61 }
62 
64 {
67 }
68 
70 {
73 }
74 
76 {
79 }
80 
82 {
85 }
86 
88 {
90  --depth;
91 }
92 
94 {
97 }
98 
100 {
103 }
104 
106 {
109 }
110 
112 {
114  --depth;
115 }
116 
118 {
122 }
123 
125 {
129 }
130 
132 {
136 }
137 
139 {
143 }
144 
146 {
147  error_orphan_elif() << "Orphan #elif" << emit();
148 }
149 
151 {
152  error_orphan_else() << "Orphan #else" << emit();
153 }
154 
156 {
157  error_orphan_endif() << "Orphan #endif" << emit();
158 }
159 
161 {
162  error_eof_too_soon() << "Unexpected end of file" << emit();
163 }
164 
165 
167 if_control::transition_table[IF_STATE_COUNT][LT_SENTINEL] = {
168  /* IF_STATE_OUTSIDE*/
169  {
170  Fpass,
171  Ftrue,
172  Ffalse,
173  orphan_elif,
174  orphan_elif,
175  orphan_elif,
176  orphan_else,
177  orphan_endif,
180  },
181  /* IF_STATE_FALSE_PREFIX*/
182  {
183  Fdrop,
184  Fdrop,
185  Fdrop,
186  Mpass,
187  Strue,
188  Sfalse,
189  Selse,
190  Dendif,
192  early_eof
193  },
194  /* IF_STATE_TRUE_PREFIX*/
195  {
196  Fpass,
197  Ftrue,
198  Ffalse,
199  Dfalse,
200  Dfalse,
201  Dfalse,
202  Delse,
203  Dendif,
205  early_eof
206  },
207  /* IF_STATE_PASS_MIDDLE*/
208  {
209  Fpass,
210  Ftrue,
211  Ffalse,
212  Pelif,
213  Mtrue,
214  Delif,
215  Pelse,
216  Pendif,
218  early_eof
219  },
220  /* IF_STATE_FALSE_MIDDLE*/
221  {
222  Fdrop,
223  Fdrop,
224  Fdrop,
225  Pelif,
226  Mtrue,
227  Delif,
228  Pelse,
229  Pendif,
231  early_eof
232  },
233  /* IF_STATE_TRUE_MIDDLE*/
234  {
235  Fpass,
236  Ftrue,
237  Ffalse,
238  Melif,
239  Melif,
240  Melif,
241  Melse,
242  Pendif,
244  early_eof
245  },
246  /* IF_STATE_PASS_ELSE*/
247  {
248  Fpass,
249  Ftrue,
250  Ffalse,
251  orphan_elif,
252  orphan_elif,
253  orphan_elif,
254  orphan_else,
255  Pendif,
257  early_eof
258  },
259  /* IF_STATE_FALSE_ELSE*/
260  {
261  Fdrop,
262  Fdrop,
263  Fdrop,
264  orphan_elif,
265  orphan_elif,
266  orphan_elif,
267  orphan_else,
268  Dendif,
270  early_eof
271  },
272  /* IF_STATE_TRUE_ELSE*/
273  {
274  Fpass,
275  Ftrue,
276  Ffalse,
277  orphan_elif,
278  orphan_elif,
279  orphan_elif,
280  orphan_else,
281  Dendif,
283  early_eof
284  },
285  /* IF_STATE_FALSE_TRAILER*/
286  {
287  Fdrop,
288  Fdrop,
289  Fdrop,
290  Dfalse,
291  Dfalse,
292  Dfalse,
293  Delse,
294  Dendif,
296  early_eof
297  }
298  /*IF TRUE FALSE ELIF ELTRUE ELFALSE ELSE ENDIF PLAIN EOF*/
299 };
300 
302 {
303  size_t deep = ++depth;
304  if (deep >= MAXDEPTH) {
305  error_too_deep() << "Too many levels of nesting" << emit();
306  }
308 }
309 
311 {
313  transition_table[state][linetype]();
314 }
315 
317 {
318  if_state state =
319  ifstate[if_depth()];
320  return state == IF_STATE_FALSE_PREFIX ||
321  state == IF_STATE_FALSE_MIDDLE ||
322  state == IF_STATE_FALSE_ELSE ||
323  state == IF_STATE_FALSE_TRAILER;
324 }
325 
327 {
328  if_state state =
329  ifstate[if_depth()];
330  return state == IF_STATE_OUTSIDE ||
331  state == IF_STATE_TRUE_PREFIX ||
332  state == IF_STATE_TRUE_MIDDLE ||
333  state == IF_STATE_TRUE_ELSE ;
334 }
335 
336 /* EOF*/
static void orphan_else()
Diagnose an input orphan #else on cerr
Definition: if_control.cpp:150
static parsed_line & cur_line()
Get a reference to the current output line.
Definition: line_despatch.h:68
We have an else after a true state.
Definition: if_control.h:78
static void print()
Print the current output line.
Definition: line_despatch.h:78
static transition_t *const transition_table[IF_STATE_COUNT][LT_SENTINEL]
The #if-state transition table.
Definition: if_control.h:147
static void Pendif()
State transition.
Definition: if_control.cpp:87
static void Selse()
State transition.
Definition: if_control.cpp:69
error_msg< 2 > error_orphan_else
Report an orphan #else was found in input.
Definition: diagnostic.h:726
We have a false elif after a pass state.
Definition: if_control.h:72
An #if directive.
static void Melse()
State transition.
Definition: if_control.cpp:138
static void early_eof()
Diagnose unexpected end of input on cerr
Definition: if_control.cpp:160
static bool is_unconditional_line()
Is the current line outside any #if scope or in the scope of a satisfied #if?
Definition: if_control.cpp:326
static void Dfalse()
State transition.
Definition: if_control.cpp:93
static void flush_all()
Emit any queued diagnostics.
Definition: diagnostic.cpp:191
static bool dead_line()
Is the current line rejected?
Definition: if_control.cpp:316
error_msg< 1 > error_orphan_elif
Report an orphan #elif was found in input.
Definition: diagnostic.h:724
static void Delse()
State transition.
Definition: if_control.cpp:105
static void set_state(if_state is)
Set the #if-state at the current nesting depth.
Definition: if_control.h:153
static size_t if_start_lines[MAXDEPTH]
Array of start lines of nested #if-directives.
Definition: if_control.h:243
static size_t if_depth()
Get the current depth of #if-nesting.
Definition: if_control.h:118
All elifs after a true are false.
Definition: if_control.h:82
error_msg< 4 > error_eof_too_soon
Report unexpected end of input.
Definition: diagnostic.h:730
static void Melif()
State transition.
Definition: if_control.cpp:131
unsigned num() const
Get the greatest source line number spanned by this line.
Definition: parsed_line.h:70
error_msg< 3 > error_orphan_endif
Report an orphan #endif was found in input.
Definition: diagnostic.h:728
An #endif directive.
The first non-false (el)if is true.
Definition: if_control.h:68
static if_state state()
Get the current #if-state.
Definition: if_control.h:123
We have a true elif after a pass state.
Definition: if_control.h:74
We have an else after only false states.
Definition: if_control.h:80
error_msg< 10 > error_too_deep
Report that #if nesting exceeds maxdepth in input.
Definition: diagnostic.h:742
static void Delif()
State transition.
Definition: if_control.cpp:99
static void Pelif()
State transition.
Definition: if_control.cpp:75
void( transition_t)
Type of #if-state transition functions.
Definition: if_control.h:141
The tag class is inserted in a diagnostic_base to tell it to emit itself.
Definition: diagnostic.h:77
static void orphan_endif()
Diagnose an input orphan #endif on cerr
Definition: if_control.cpp:155
static void Strue()
State transition.
Definition: if_control.cpp:57
static void drop()
Drop the current output line.
Definition: line_despatch.h:73
An #else directive.
static void Mtrue()
State transition.
Definition: if_control.cpp:124
The first non-false (el)if is insoluble.
Definition: if_control.h:70
if_state
symbolic constants denoting the if-control states.
Definition: if_control.h:62
static if_state ifstate[MAXDEPTH]
Array of states of nested #if-directives.
Definition: if_control.h:237
static void Mpass()
State transition.
Definition: if_control.cpp:117
static void Dendif()
State transition.
Definition: if_control.cpp:111
static size_t depth
Current depth of #if-nesting.
Definition: if_control.h:240
void keyword_edit()
Replace the directive in the line.
static void Sfalse()
State transition.
Definition: if_control.cpp:63
Sentinel.
Definition: line_type.h:78
line_type
Enumeration of types of input lines.
Definition: line_type.h:52
static void Pelse()
State transition.
Definition: if_control.cpp:81
static void orphan_elif()
Diagnose an input orphan #elif on cerr
Definition: if_control.cpp:145
We are outside any if
Definition: if_control.h:64
We have a false if followed by false elif
Definition: if_control.h:66
static const unsigned MAXDEPTH
Maximum depth of hash-if nesting.
Definition: if_control.h:138
We have an else after a pass state.
Definition: if_control.h:76
static void transition(line_type linetype)
Transition the if-control state given an evaluated line type.
Definition: if_control.cpp:310
static void nest()
Increment the #if-nesting depth.
Definition: if_control.cpp:301