coan  6.0.1
A C/C++ Configuration Analyzer
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
parsed_line.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2013 Mike Kinghan, imk@burroingroingjoing.com *
3  * All rights reserved. *
4  * *
5  * Contributed originally by Mike Kinghan, imk@burroingroingjoing.com *
6  * *
7  * Redistribution and use in source and binary forms, with or without *
8  * modification, are permitted provided that the following conditions *
9  * are met: *
10  * *
11  * Redistributions of source code must retain the above copyright *
12  * notice, this list of conditions and the following disclaimer. *
13  * *
14  * Redistributions in binary form must reproduce the above copyright *
15  * notice, this list of conditions and the following disclaimer in the *
16  * documentation and/or other materials provided with the distribution. *
17  * *
18  * Neither the name of Mike Kinghan nor the names of its contributors *
19  * may be used to endorse or promote products derived from this software *
20  * without specific prior written permission. *
21  * *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS *
29  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED *
30  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,*
31  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF *
32  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
33  * DAMAGE. *
34  * *
35  **************************************************************************/
36 
41 #include "parsed_line.h"
42 #include "io.h"
43 #include "lexicon.h"
44 #include "if_control.h"
45 #include "line_despatch.h"
46 #include "options.h"
47 #include "diagnostic.h"
48 #include "citable.h"
49 
51 
52 using namespace std;
53 
54 size_t parsed_line::extend()
55 {
56  string line;
57  getline(*_in,line);
58  if (_in->fail() && !_in->eof()) {
59  abend_cant_read_input() << "Read error on file "
60  << io::in_file_name() << emit();
61  return 0;
62  }
63  size_t bytes = line.length();
64  if (!_in->eof()) {
65  line += '\n';
66  ++bytes;
67  } else if (bytes > 0) {
69  "Missing newline at end of file" << emit();
70  }
71  _text += line;
72  _lineno += bytes != 0;
73  return bytes;
74 }
75 
76 size_t parsed_line::extend(size_t skip)
77 {
78  if (skip) {
79  ++_extensions;
80  size_t bytes = extend();
81  if (bytes) {
82  return skip;
83  }
84  error_eof_too_soon() << "Unexpected end of file" << emit();
85  }
86  return skip;
87 }
88 
89 bool parsed_line::get()
90 {
91  bool got;
92  _extensions = 0;
93  _simplified = false;
94  clear();
95  got = extend();
96  set_dropping();
97  return got;
98 }
99 
100 
101 void parsed_line::keyword_lop(std::string const & keyword) {
102  _text.resize(_keyword_posn);
103  _text += keyword;
104  _text += '\n';
105  _keyword_len = keyword.length();
107 }
108 
109 void parsed_line::keyword_swap(std::string const & directive) {
110  _text.replace(_keyword_posn,_keyword_len,directive);
111  _keyword_len = directive.length();
113 }
114 
115 template<> void parsed_line::keyword_edit<directive_type::HASH_IF>() {
116  keyword_swap(TOK_IF);
117 }
118 
119 template<> void parsed_line::keyword_edit<directive_type::HASH_IFDEF>() {
120  keyword_swap(TOK_IFDEF);
121 }
122 
123 template<> void parsed_line::keyword_edit<directive_type::HASH_IFNDEF>() {
124  keyword_swap(TOK_IFNDEF);
125 }
126 
127 template<> void parsed_line::keyword_edit<directive_type::HASH_ELSE>() {
128  keyword_lop(TOK_ELSE);
129 }
130 
131 template<> void parsed_line::keyword_edit<directive_type::HASH_ELIF>() {
132  keyword_swap(TOK_ELIF);
133 }
134 
135 template<> void parsed_line::keyword_edit<directive_type::HASH_ENDIF>() {
136  keyword_lop(TOK_ENDIF);
137 }
138 
140 {
141  _dropping = if_control::dead_line() ^ options::complement();
142 }
143 
145 {
146  if (_dtype == COMMANDLINE) {
147  _reportable = true;
148  return;
149  }
150  bool verdict;
151  switch(options::get_command()) {
152  case CMD_SYMBOLS:
153  switch(_dtype) {
154  case HASH_IFDEF:
155  case HASH_IFNDEF:
156  case HASH_IF:
157  verdict = options::list_symbols_in_ifs();
158  break;
159  case HASH_DEFINE:
160  verdict = options::list_symbols_in_defs();
161  break;
162  case HASH_UNDEF:
164  break;
165  case HASH_INCLUDE:
167  break;
168  case HASH_LINE:
169  verdict = options::list_symbols_in_lines();
170  break;
171  case HASH_UNKNOWN:
172  verdict = false;
173  break;
174  default:
175  verdict = true;
176  }
177  break;
178  case CMD_INCLUDES:
179  verdict = _dtype == HASH_INCLUDE;
180  break;
181  case CMD_DEFS:
182  verdict = _dtype == HASH_DEFINE || _dtype == HASH_UNDEF;
183  break;
184  case CMD_PRAGMAS:
185  verdict = _dtype == HASH_PRAGMA;
186  break;
187  case CMD_ERRORS:
188  verdict = _dtype == HASH_ERROR;
189  break;
190  case CMD_LINES:
191  verdict = _dtype == HASH_LINE;
192  break;
193  case CMD_DIRECTIVES:
194  verdict = _dtype != HASH_UNKNOWN;
195  break;
196  default:
197  verdict = false;
198  }
199  if (verdict) {
201  verdict = _dropping && !if_control::is_unconditional_line();
202  } else if (options::list_only_active()) {
203  verdict = !_dropping && if_control::is_unconditional_line();
204  }
205  }
206  _reportable = verdict;
207 }
208 
210  *_out << _text;
211 }
212 
214 {
215  size_t i = 0;
216  for ( ;i < _indent; ++i) {
217  *_out << _text[i];
218  }
219  string output = citable(!options::plaintext(),*this,i);
220  line_despatch::lines_changed() += _extensions + 1;
221  *_out << output << '\n';
223  for ( ; _extensions; --_extensions) {
224  *_out << '\n';
225  }
227  for ( ; _extensions; --_extensions) {
228  *_out << "//coan <\n";
229  }
230  }
231 }
232 
234 {
235  if (!is_simplified()) {
237  if (!_extensions) {
238  *_out << "//coan < ";
239  write_fast();
240  } else {
241  line_despatch::lines_changed() += _extensions;
242  size_t start = 0;
243  size_t end = _text.find('\n');
244  for ( ;end != string::npos;
245  start = end + 1,end = _text.find('\n',start)) {
246  *_out << "//coan < ";
247  *_out << _text.substr(start,1 + end - start);
248  }
249  }
250  } else {
251  *_out << "//coan < ";
252  write_slow();
253  }
254 }
255 
256 void parsed_line::write()
257 {
258  if (!is_simplified()) {
259  write_fast();
260  } else {
261  write_slow();
262  }
263 }
264 
265 void parsed_line::write(bool keep)
266 {
267  if (keep ^ options::complement()) {
268  write();
269  } else {
271  line_despatch::lines_changed() += _extensions + 1;
272  *_out << '\n';
273  for ( ; _extensions; --_extensions) {
274  *_out << '\n';
275  }
276  } else if (options::get_discard_policy() == DISCARD_DROP) {
277  line_despatch::lines_suppressed() += _extensions + 1;
278  } else {
279  write_commented_out();
280  }
281  }
282 }
283 
284 void parsed_line::output()
285 {
287  if (cmd == CMD_SOURCE || cmd == CMD_SPIN) {
288  if (options::line_directives()) {
289  if (_drop_run_length) {
290  _drop_run_length = 0;
291  if (_extensions) {
292  --_lineno;
293  }
294  *_out << "#line " << _lineno << '\n';
297  }
298  }
299  write(true);
300  }
301 }
302 
303 void parsed_line::drop()
304 {
306  || options::get_command() == CMD_SPIN) {
307  write(false);
308  if (options::line_directives()) {
309  ++_drop_run_length;
310  }
311  }
312 }
313 
315 
316 // EOF
The directives command.
Definition: options.h:82
static bool plaintext()
Are we to omit parsing for C/C++ comments?
Definition: options.h:183
void write_slow()
Output the line slowely, when necessary.
void set_reportable()
Record whether the line is reportable for the operative command.
static discard_policy & get_discard_policy()
Get the policy for discarding lines.
Definition: options.h:175
static bool list_only_active()
Do we list items only from operative directives?
Definition: options.h:125
static bool line_directives()
Do we output #line directives?
Definition: options.h:179
static bool list_symbols_in_includes()
Do we list symbols in #include directives?
Definition: options.h:145
#define TOK_IFNDEF
Constant denoting the #ifndef directive.
Definition: lexicon.h:50
The symbols command.
Definition: options.h:76
Blank discarded lines.
Definition: options.h:52
The line command.
Definition: options.h:81
void keyword_lop(std::string const &keyword)
Convert the directive in the line into a another one that has no argument.
static bool list_only_inactive()
Do we list items only from inoperative directives?
Definition: options.h:129
void write()
Output the line.
void keyword_swap(std::string const &directive)
Replace the directive keyword in the line with another one.
An #if directive.
Encapsulates a directive of a given type.
Definition: directive.h:141
static command_code get_command()
Get the operative coan command code.
Definition: options.cpp:247
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 bool dead_line()
Is the current line rejected?
Definition: if_control.cpp:316
The defs command.
Definition: options.h:78
A #line directive.
An #ifndef directive.
#define TOK_ELSE
Constant denoting the #else directive.
Definition: lexicon.h:52
A #pragma directive.
static bool complement()
Are we to output lines instead of dropping them and vice versa?
Definition: options.h:161
static unsigned & lines_changed()
Get a reference to the count of changed lines.
The commandline, considered as a #define/#undef
#define TOK_ELIF
Constant denoting the #elif directive.
Definition: lexicon.h:54
error_msg< 4 > error_eof_too_soon
Report unexpected end of input.
Definition: diagnostic.h:730
static std::string in_file_name()
Get the name of the current source file.
Definition: io.h:105
std::string citable(chewer< std::string > &chew, size_t len=std::string::npos)
Make a citable version of length-delimited text.
bool get()
Try to read a line of input.
#define TOK_IFDEF
Constant denoting the #ifdef directive.
Definition: lexicon.h:48
void write_commented_out()
Output the line commented out.
The errors command.
Definition: options.h:80
static unsigned & lines_suppressed()
Get a reference to the count of suppressed lines.
abend_msg< 5 > abend_cant_read_input
Report read error on input.
Definition: diagnostic.h:794
The pragmas command.
Definition: options.h:79
Drop discarded lines.
Definition: options.h:51
The tag class is inserted in a diagnostic_base to tell it to emit itself.
Definition: diagnostic.h:77
An #undef directive.
#define TOK_ENDIF
Constant denoting the #endif directive.
Definition: lexicon.h:56
An unknown directive.
size_t extend() override
Try to read another line of input, returning the number of bytes read.
Comment discarded lines.
Definition: options.h:53
An #include directive.
The includes command.
Definition: options.h:77
static bool list_symbols_in_defs()
Do we list symbols in #define directives?
Definition: options.h:137
An #error directive.
void write_fast()
Output the line fast, when possible.
warning_msg< 11 > warning_missing_eof_newline
Report a newline is missing at end of input.
Definition: diagnostic.h:669
void drop()
Drop the line.
the spin command
Definition: options.h:83
static bool list_symbols_in_ifs()
Do we list items only from inoperative directives?
Definition: options.h:133
command_code
Sequential symbolic constants for coan commands.
Definition: options.h:72
An #ifdef directive.
static bool list_symbols_in_lines()
Do we list symbols in #line directives?
Definition: options.h:149
void output()
Output the line.
void set_dropping()
Record whether we are dropping the line.
#define TOK_IF
Constant denoting the if directive.
Definition: lexicon.h:46
An #define directive.
static bool list_symbols_in_undefs()
Do we list symbols in #undef directives?
Definition: options.h:141
The source command.
Definition: options.h:75