coan  6.0.1
A C/C++ Configuration Analyzer
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
explained_expansion.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2007-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 #include "explained_expansion.h"
37 #include "diagnostic.h"
38 #include <iostream>
39 #include <iomanip>
40 
45 
47 using namespace std;
48 
49 unsigned
51  explained_expansion const & e,
52  bool do_self)
53 {
54  unsigned edits = 0;
55  if (!do_self) {
56  if (_parent) {
57  edits += _parent->bubble_edit(e,true);
58  }
59  } else {
60  if (!args_expansion_done()) {
61  edits += edit_trailing_args(e,_cur_arg);
62  } else {
63  edits += edit_buf(_value,e);
64  }
65  if (edits && _parent) {
66  edits += _parent->bubble_edit(e,true);
67  }
68  }
69  if (edits && !_parent) {
70  report_intermediate_value();
71  }
72  return edits;
73 }
74 
76 {
77  unsigned edits = 0;
78  if (args()) {
79  for ( auto i = seek_expandable_arg();
80  i != args().size(); ++_cur_arg,
81  i = seek_expandable_arg()) {
82  edits += expand(args()[i]);
83  }
84  edits += substitute();
85  } else if (!callee()->defn()) {
86  _value = "0";
87  ++edits;
88  } else if (callee()->defn()->empty()) {
89  _value = "";
90  ++edits;
91  }
92  else {
93  _value = callee()->format()->str();
94  ++edits;
95  }
96  if (edits) {
97  edits += bubble_edit(*this,false);
98  report_intermediate_value();
99  }
100  return edits += expand(_value);
101 }
102 
103 unsigned explained_expansion::expand(string & str)
104 {
105  unsigned edits = 0;
106  symbol::locator sym;
107  size_t off;
108  chewer<string> chew(chew_mode::plaintext,str);
109  for ( ;(sym = symbol::find_any_in(chew,off)),sym; chew.sync()) {
110  reference ref(sym,chew,this);
111  if (!sym->configured() && !sym->in_progress()) {
112  chew = off + sym->id().length();
113  continue;
114  }
115  explained_expansion e(ref,this);
116  try {
117  if (!e.expand()) {
118  continue;
119 
120  }
121  }
122  catch(expansion_base const & eb) {
123  if (eb == e) {
125  << "Macro expansion of \"" << eb.reference::invocation()
126  << "\" abandoned. Will exceed max expansion size "
127  << max_expansion_size() << " bytes" << emit();
128  throw_self();
129  }
130  }
131  if (str.compare(off,e.value().size(),e.value()) == 0) {
132  continue;
133  }
134  edit(str,off,e.invocation().size(),e.value());
135  ++edits;
136  edits += edit_buf(str,e,off + e.invocation().size());
137  edits += edit_trailing_args(e,_cur_arg + 1);
138  if (edits) {
139  edits += bubble_edit(e,false);
140  report_intermediate_value();
141  }
142  }
143  return edits;
144 }
145 
147 {
148  if (!_parent && explaining()) {
149  cout << "Edit #" << setw(3) << setfill('0') << ++_step << ": >>"
150  << (args_expansion_done() ? value() : invocation())
151  << "<<" << endl;
152  }
153 }
154 
156 
157 // EOF
struct symbol::locator encapsulates a symbol table entry.
Definition: symbol.h:79
bool in_progress() const
Say whether a determination the symbol's state is in progress.
Definition: symbol.h:297
static locator find_any_in(chewer< CharSeq > &chew, size_t &off)
Search a terminal portion of a CharSeq for any known symbol name.
std::string const & id() const
Get the name of the symbol.
Definition: symbol.h:172
bool configured() const
Say whether the symbol is configured.
Definition: symbol.h:258
warning_msg< 35 > warning_incomplete_expansion
Report a macro reference not fully expanded.
Definition: diagnostic.h:721
struct explained_expansion encapsulates macro-expansion of a reference when the --explain option is o...
The tag class is inserted in a diagnostic_base to tell it to emit itself.
Definition: diagnostic.h:77
unsigned expand() override
Perform the explained expansion of the reference, returning the numbe of edits applied.
`template struct chewer<CharSeq> is a cursor-like type that is associated with a character-sequence t...
Definition: chew.h:248
std::string const & value() const
Get the current expanded value of the reference.
struct expansion_base is an abstract base for classes that encapsulate a mode of macro-expansion of a...
std::string const & invocation() const override
Get a string representing the invocation of the reference with the current expansions of its argument...
void report_intermediate_value()
Report the latest value of the expansion.
unsigned bubble_edit(explained_expansion const &e, bool do_self=true)
Recursively replace remaining occurrences of a reference in the parents of this explained_expansion a...