coan  6.0.1
A C/C++ Configuration Analyzer
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
parameter_substitution.h
Go to the documentation of this file.
1 #ifndef PARAMETER_SUBSTUTION_H
2 #define PARAMETER_SUBSTUTION_H
3 #pragma once
4 /***************************************************************************
5  * Copyright (C) 2007-2013 Mike Kinghan, imk@burroingroingjoing.com *
6  * All rights reserved. *
7  * *
8  * Contributed originally by Mike Kinghan, imk@burroingroingjoing.com *
9  * *
10  * Redistribution and use in source and binary forms, with or without *
11  * modification, are permitted provided that the following conditions *
12  * are met: *
13  * *
14  * Redistributions of source code must retain the above copyright *
15  * notice, this list of conditions and the following disclaimer. *
16  * *
17  * Redistributions in binary form must reproduce the above copyright *
18  * notice, this list of conditions and the following disclaimer in the *
19  * documentation and/or other materials provided with the distribution. *
20  * *
21  * Neither the name of Mike Kinghan nor the names of its contributors *
22  * may be used to endorse or promote products derived from this software *
23  * without specific prior written permission. *
24  * *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
28  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *
29  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS *
32  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED *
33  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,*
34  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF *
35  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
36  * DAMAGE. *
37  * *
38  **************************************************************************/
39 
40 #include "chew.h"
41 #include <string>
42 #include <vector>
43 
44 // Forward decl
45 struct symbol;
46 struct parameter_list;
47 
57 namespace parameter_substitution {
59 
61 enum class demarcator : char
62 {
63  soh = '\001',
64  stx = '\002',
65  etx = '\003',
66  ack = '\006',
67  nak = '\025',
68  sub = '\032',
69  esc = '\033'
70 };
71 
72 
76 enum class handling : char
77 {
79  substitute_arg = char(demarcator::etx),
81  substitute_expanded_arg = char(demarcator::sub),
83  substitute_quoted_arg = char(demarcator::esc),
84 };
85 
89 struct specifier
90 {
92  static const size_t serialized_size = 4;
93 
96  : _bytes{0}{}
97 
101  specifier(unsigned short param_i, handling h) {
102  _bytes[0] = char(demarcator::stx);
103  set_param_index(param_i);
104  set_handling(h);
105  }
106 
108  bool operator==(specifier const & other) const {
109  return _bytes[0] == other._bytes[0] &&
110  _bytes[1] == other._bytes[1] &&
111  _bytes[2] == other._bytes[2] &&
112  _bytes[3] == other._bytes[3];
113  }
114 
116  bool operator!=(specifier const & other) const {
117  return !(*this == other);
118  }
119 
121  void append_to(std::string & s) {
122  for (size_t i = 0; i < sizeof(_bytes); ++i) {
123  s += _bytes[i];
124  }
125  }
126 
128  void set_param_index(unsigned short i) {
129  _bytes[1] = i >> 8;
130  _bytes[2] = (char)i;
131  }
132 
134  unsigned short get_param_index() const {
135  return (_bytes[1] << 8) | _bytes[2];
136  }
137 
140  _bytes[3] = (char)h;
141  }
142 
145  return handling(_bytes[3]);
146  }
147 
149  bool null() const {
150  return _bytes[0] == 0;
151  }
152 
154  explicit operator bool() const {
155  return !null();
156  }
157 
167  if (chew && *chew == char(demarcator::stx) && !chew.overshoot(3)) {
168  char h = chew[3];
169  if (h == char(handling::substitute_arg) ||
171  h == char(handling::substitute_quoted_arg)) {
172  unsigned short param_i = (chew[1] << 8) | chew[2];
173  chew += serialized_size;
174  return specifier(param_i,handling(h));
175  }
176  }
177  return specifier();
178  }
179 
192  static size_t get_at(
193  std::string const & str,
194  size_t off,
195  size_t & i_off,
196  size_t & h_off) {
197  if (str[off] == char(demarcator::stx) && off + 3 < str.size()) {
198  char h = str[off + 3];
199  if (h == char(handling::substitute_arg) ||
201  h == char(handling::substitute_quoted_arg) ) {
202  i_off = off + 1;
203  h_off = off + 3;
204  return off;
205  }
206  }
207  return std::string::npos;
208  }
209 
222  static size_t get_ending_at(
223  std::string const & str,
224  size_t off,
225  size_t & i_off,
226  size_t & h_off) {
227  ptrdiff_t start = off - 3;
228  if (start >= 0 && str[start] == char(demarcator::stx)) {
229  char h = str[off];
230  if (h == char(handling::substitute_arg) ||
232  h == char(handling::substitute_quoted_arg) ) {
233  i_off = off - 2;
234  h_off = off;
235  return start;
236  }
237  }
238  return std::string::npos;
239  }
240 
242  std::string legible() const;
243 
244 private:
245 
248 
249 };
250 
257 struct format
258 {
260  explicit format(symbol & sym);
261 
263  std::string const & str() const {
264  return _fmt;
265  }
266 
268  std::string legible() const;
269 
273  static std::string legible(std::string const & pb);
274 
275 private:
276 
283  void build_format(symbol & sym);
284 
298  void do_stringify_adjustments(size_t nparams);
299 
318 
335  ptrdiff_t adjust_for_stringify_op(size_t pos, size_t nparams);
336 
354  ptrdiff_t adjust_for_token_paste_op(size_t pos);
355 
357  std::string _fmt;
359  std::vector<size_t> _stringify_offs;
361  std::vector<size_t> _token_paste_offs;
362 };
363 
364 } // namespace parameter_substitution
365 
366 #endif // EOF
Substitute the argument literally enclosed in double quotes.
std::string legible() const
Get a string legibly representing the specifier.
handling
Enumerated constants denoting the manner in which an argument is to be substituted for a macro parame...
std::string legible() const
Get a string legibly representing the format.
ptrdiff_t adjust_for_stringify_op(size_t pos, size_t nparams)
Adjust the format for a '#'-operator.
char _bytes[serialized_size]
The specifier data.
demarcator
Non-printable fields in a substitution format.
ptrdiff_t adjust_for_token_paste_op(size_t pos)
Adjust the format for a '##'-operator.
bool operator!=(specifier const &other) const
Inequality.
std::vector< size_t > _token_paste_offs
Vector of offset of ##-operators.
struct parameter_substitution::format encapsulates a parameter substitution format.
static size_t get_at(std::string const &str, size_t off, size_t &i_off, size_t &h_off)
Attempt to detect a specifier from a string position.
std::string const & str() const
Get a reference to the format string.
bool overshoot(size_t off=0) const
Say whether the scanning position is past the end of the associated sequence_type ...
Definition: chew.h:344
Substitute the full macro expansion of the argument.
bool null() const
Say whether the specifier is null.
void append_to(std::string &s)
Append the specifier to a string.
void build_format(symbol &sym)
Build a format with appropriate specifiers inserted at all parameter positions.
handling get_handling() const
Get the handling of the specified parameter.
void do_stringify_adjustments(size_t nparams)
After building the first-cut format, make any necessary adjustments for the presence of '#'-operators...
specifier(unsigned short param_i, handling h)
Construct a specifier for the parameter indexed param_i to be handled in manner h ...
struct paramater_substitution::specifier encapsulates a parameter substitution specifier.
unsigned short get_param_index() const
Get the index of the specified parameter.
`template struct chewer<CharSeq> is a cursor-like type that is associated with a character-sequence t...
Definition: chew.h:248
static size_t get_ending_at(std::string const &str, size_t off, size_t &i_off, size_t &h_off)
Attempt to detect a specifier ending at a string position.
void set_handling(handling h)
Set the handling of the specified parameter.
std::vector< size_t > _stringify_offs
Vector of offsets of #-operators.
std::string _fmt
The format string.
format(symbol &sym)
Construct a parameter substitution format for a given symbol.
void do_token_paste_adjustments()
After building the first-cut format, make any necessary adjustments for the presence of '##'-operator...
struct symbol encapsulates a preprocessor symbol's state
Definition: symbol.h:58
static specifier read(chewer< std::string > &chew)
Attempt to read a specifier from a chewer<std::string>.
bool operator==(specifier const &other) const
Equality.
specifier()
The default constructor yields the null specifier.
Substitute the argument literally.
void set_param_index(unsigned short i)
Set the index of the specified parameter.
static const size_t serialized_size
Serialized size of a substitution specifier.