1
/****************************************************************************
3
** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
4
** Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
6
** This file is part of $PRODUCT$.
10
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13
****************************************************************************/
15
#ifndef PP_MACRO_EXPANDER_H
16
#define PP_MACRO_EXPANDER_H
22
pp_macro *expanding_macro;
23
std::vector<std::string> *actuals;
25
pp_frame (pp_macro *__expanding_macro, std::vector<std::string> *__actuals):
26
expanding_macro (__expanding_macro), actuals (__actuals) {}
29
class pp_macro_expander
34
pp_skip_number skip_number;
35
pp_skip_identifier skip_identifier;
36
pp_skip_string_literal skip_string_literal;
37
pp_skip_char_literal skip_char_literal;
38
pp_skip_argument skip_argument;
39
pp_skip_comment_or_divop skip_comment_or_divop;
40
pp_skip_blanks skip_blanks;
41
pp_skip_whitespaces skip_whitespaces;
43
std::string const *resolve_formal (pp_fast_string const *__name)
50
assert (frame->expanding_macro != 0);
52
std::vector<pp_fast_string const *> const formals = frame->expanding_macro->formals;
53
for (std::size_t index = 0; index < formals.size(); ++index)
55
pp_fast_string const *formal = formals[index];
57
if (*formal != *__name)
60
else if (frame->actuals && index < frame->actuals->size())
61
return &(*frame->actuals)[index];
64
assert (0); // internal error?
75
pp_macro_expander (pp_environment &__env, pp_frame *__frame = 0):
76
env (__env), frame (__frame), lines (0), generated_lines (0) {}
78
template <typename _InputIterator, typename _OutputIterator>
79
_InputIterator operator () (_InputIterator __first, _InputIterator __last, _OutputIterator __result)
82
__first = skip_blanks (__first, __last);
83
lines = skip_blanks.lines;
85
while (__first != __last)
89
*__result++ = *__first;
92
__first = skip_blanks (++__first, __last);
93
lines += skip_blanks.lines;
95
if (__first != __last && *__first == '#')
98
else if (*__first == '#')
100
__first = skip_blanks (++__first, __last);
101
lines += skip_blanks.lines;
103
_InputIterator end_id = skip_identifier (__first, __last);
105
// ### rewrite: not safe
106
char name_buffer[512], *cp = name_buffer;
107
std::copy (__first, end_id, cp);
108
std::size_t name_size = end_id - __first;
109
name_buffer[name_size] = '\0';
111
pp_fast_string fast_name (name_buffer, name_size);
113
if (std::string const *actual = resolve_formal (&fast_name))
117
for (std::string::const_iterator it = skip_whitespaces (actual->begin (), actual->end ());
118
it != actual->end (); ++it)
126
else if (*it == '\n')
141
*__result++ = '#'; // ### warning message?
143
else if (*__first == '\"')
145
_InputIterator next_pos = skip_string_literal (__first, __last);
146
lines += skip_string_literal.lines;
147
std::copy (__first, next_pos, __result);
150
else if (*__first == '\'')
152
_InputIterator next_pos = skip_char_literal (__first, __last);
153
lines += skip_char_literal.lines;
154
std::copy (__first, next_pos, __result);
157
else if (_PP_internal::comment_p (__first, __last))
159
__first = skip_comment_or_divop (__first, __last);
160
int n = skip_comment_or_divop.lines;
166
else if (pp_isspace (*__first))
168
for (; __first != __last; ++__first)
170
if (*__first == '\n' || !pp_isspace (*__first))
176
else if (pp_isdigit (*__first))
178
_InputIterator next_pos = skip_number (__first, __last);
179
lines += skip_number.lines;
180
std::copy (__first, next_pos, __result);
183
else if (pp_isalpha (*__first) || *__first == '_')
185
_InputIterator name_begin = __first;
186
_InputIterator name_end = skip_identifier (__first, __last);
187
__first = name_end; // advance
189
// search for the paste token
190
_InputIterator next = skip_blanks (__first, __last);
191
if (next != __last && *next == '#')
194
if (next != __last && *next == '#')
195
__first = skip_blanks(++next, __last);
198
// ### rewrite: not safe
200
std::ptrdiff_t name_size;
201
#if defined(__SUNPRO_CC)
202
std::distance (name_begin, name_end, name_size);
204
name_size = std::distance (name_begin, name_end);
206
assert (name_size >= 0 && name_size < 512);
208
char name_buffer[512], *cp = name_buffer;
209
std::size_t __size = name_end - name_begin;
210
std::copy (name_begin, name_end, cp);
211
name_buffer[__size] = '\0';
213
pp_fast_string fast_name (name_buffer, name_size);
215
if (std::string const *actual = resolve_formal (&fast_name))
217
std::copy (actual->begin (), actual->end (), __result);
221
static bool hide_next = false; // ### remove me
223
pp_macro *macro = env.resolve (name_buffer, name_size);
224
if (! macro || macro->hidden || hide_next)
226
hide_next = ! strcmp (name_buffer, "defined");
228
if (__size == 8 && name_buffer [0] == '_' && name_buffer [1] == '_')
230
if (! strcmp (name_buffer, "__LINE__"))
233
char *end = buf + pp_snprintf (buf, 16, "%d", env.current_line + lines);
235
std::copy (&buf [0], end, __result);
239
else if (! strcmp (name_buffer, "__FILE__"))
242
std::copy (env.current_file.begin (), env.current_file.end (), __result); // ### quote
248
std::copy (name_begin, name_end, __result);
252
if (! macro->function_like)
256
if (macro->definition)
258
macro->hidden = true;
263
pp_macro_expander expand_macro (env);
264
expand_macro (macro->definition->begin (), macro->definition->end (), std::back_inserter (__tmp));
265
generated_lines += expand_macro.lines;
267
if (! __tmp.empty ())
269
std::string::iterator __begin_id = skip_whitespaces (__tmp.begin (), __tmp.end ());
270
std::string::iterator __end_id = skip_identifier (__begin_id, __tmp.end ());
272
if (__end_id == __tmp.end ())
275
__id.assign (__begin_id, __end_id);
278
#if defined(__SUNPRO_CC)
279
std::distance (__begin_id, __end_id, x);
281
x = std::distance (__begin_id, __end_id);
283
m = env.resolve (__id.c_str (), x);
287
std::copy (__tmp.begin (), __tmp.end (), __result);
290
macro->hidden = false;
299
// function like macro
300
_InputIterator arg_it = skip_whitespaces (__first, __last);
302
if (arg_it == __last || *arg_it != '(')
304
std::copy (name_begin, name_end, __result);
305
lines += skip_whitespaces.lines;
310
std::vector<std::string> actuals;
312
++arg_it; // skip '('
314
pp_macro_expander expand_actual (env, frame);
316
_InputIterator arg_end = skip_argument_variadics (actuals, macro, arg_it, __last);
317
if (arg_it != arg_end)
319
std::string actual (arg_it, arg_end);
320
actuals.resize (actuals.size() + 1);
321
actuals.back ().reserve (255);
322
expand_actual (actual.begin (), actual.end(), std::back_inserter (actuals.back()));
326
while (arg_it != __last && *arg_end == ',')
328
++arg_it; // skip ','
330
arg_end = skip_argument_variadics (actuals, macro, arg_it, __last);
331
std::string actual (arg_it, arg_end);
332
actuals.resize (actuals.size() + 1);
333
actuals.back ().reserve (255);
334
expand_actual (actual.begin (), actual.end(), std::back_inserter (actuals.back()));
338
assert (arg_it != __last && *arg_it == ')');
340
++arg_it; // skip ')'
343
#if 0 // ### enable me
344
assert ((macro->variadics && macro->formals.size () >= actuals.size ())
345
|| macro->formals.size() == actuals.size());
348
pp_frame frame (macro, &actuals);
349
pp_macro_expander expand_macro (env, &frame);
350
macro->hidden = true;
351
expand_macro (macro->definition->begin (), macro->definition->end (), __result);
352
macro->hidden = false;
353
generated_lines += expand_macro.lines;
356
*__result++ = *__first++;
362
template <typename _InputIterator>
363
_InputIterator skip_argument_variadics (std::vector<std::string> const &__actuals, pp_macro *__macro,
364
_InputIterator __first, _InputIterator __last)
366
_InputIterator arg_end = skip_argument (__first, __last);
368
while (__macro->variadics && __first != arg_end && arg_end != __last && *arg_end == ','
369
&& (__actuals.size () + 1) == __macro->formals.size ())
371
arg_end = skip_argument (++arg_end, __last);
380
#endif // PP_MACRO_EXPANDER_H
382
// kate: space-indent on; indent-width 2; replace-tabs on;