25
25
#include "Puma/ErrorSink.h"
26
#include "Puma/CFunctionInfo.h"
27
#include "Puma/CArgumentInfo.h"
28
#include "Puma/CClassInfo.h"
29
#include "Puma/CTemplateInfo.h"
30
#include "Puma/CTemplateInstance.h"
31
26
#include "Puma/CTree.h"
32
27
#include "Puma/MacroUnit.h"
36
using std::stringstream;
41
29
const WeavePos &WeaverBase::weave_pos (Token *t, WeavePos::Pos p) {
43
// try to insert the position as a new one
44
pair<WPSet::iterator, bool> result = _positions.insert (WeavePos (t, p));
46
// the resulting iterator points either to the new or an existing entry
31
// check whether the weaving position has already been created
32
WPSet::iterator i = _positions.find (WeavePos (t, p));
33
if (i != _positions.end ())
36
// create an insert a marker token
37
Token *marker_token = new Token; // just a marker token without text etc.
38
marker_token->location (t->location ());
39
Unit *marker_unit = new Unit;
40
marker_unit->append (*marker_token);
41
_commander.addBuffer (marker_unit);
42
if (p == WeavePos::WP_HEADER) {
43
// check whether there is already a marker token in front of the first token
44
Token *marker_inspos = t;
45
WPSet::iterator i = _positions.find (WeavePos (t, WeavePos::WP_BEFORE));
46
if (i != _positions.end ())
47
marker_inspos = (*i)._marker;
48
_commander.move_before (marker_token, marker_token, marker_inspos);
50
else if (p == WeavePos::WP_BEFORE)
51
_commander.move_before (marker_token, marker_token, t);
52
else if (p == WeavePos::WP_FOOTER) {
53
// check whether there is already a marker token behind the last token
54
Token *marker_inspos = t;
55
WPSet::iterator i = _positions.find (WeavePos (t, WeavePos::WP_AFTER));
56
if (i != _positions.end ())
57
marker_inspos = (*i)._marker;
58
_commander.move (marker_token, marker_token, marker_inspos);
61
_commander.move (marker_token, marker_token, t);
63
// insert the position as a new one
64
pair<WPSet::iterator, bool> result =
65
_positions.insert (WeavePos (t, p, marker_token));
67
// the resulting iterator points to the new entry
47
68
return *result.first;
50
// insert the contents of a generated unit at a given position (with move)
51
void WeaverBase::paste (const WeavePos &pos, Unit *unit) {
71
// get the 'header' weaving position in front of a unit
72
const WeavePos &WeaverBase::header_pos (Unit *unit) {
73
Token *first = (Token*)unit->first ();
74
if (unit == (Unit*)_primary_start->belonging_to ())
75
first = _primary_start;
76
return weave_pos (first, WeavePos::WP_HEADER);
79
// get the 'header' weaving position in front of the primary unit
80
const WeavePos &WeaverBase::header_pos () {
81
return weave_pos (_primary_start, WeavePos::WP_HEADER);
84
// get the 'footer' weaving position at the end of an arbitrary unit
85
const WeavePos &WeaverBase::footer_pos (Unit *unit) {
86
Token *last = (Token*)unit->last ();
87
if (unit == (Unit*)_primary_end->belonging_to ())
89
return weave_pos (last, WeavePos::WP_FOOTER);
92
// get the 'footer' weaving position at the end of the primary unit
93
const WeavePos &WeaverBase::footer_pos () {
94
return weave_pos (_primary_end, WeavePos::WP_FOOTER);
97
// insert a unit at the specified weaving position
98
// 'before' selects whether the new text is inserted either before (true)
99
// or after (false) any text that has been inserted earlier at this position.
100
void WeaverBase::insert (const WeavePos &pos, Unit *unit, bool before) {
52
101
// return immediately if the there is a problem with macro manipulation
53
102
if (macro_problem (pos))
56
Token *tok = pos._token;
57
// if (tok->unit ()->isMacroExp ()) {
58
// MacroUnit *munit = (MacroUnit*)tok->unit ();
59
// if (tok == munit->first() && pos._pos == WeavePos::WP_BEFORE)
60
// tok = munit->ExpansionBegin(tok);
61
// else if (tok == munit->last() && pos._pos == WeavePos::WP_AFTER)
62
// tok = munit->ExpansionEnd(tok);
64
_commander.addBuffer (unit);
65
Token *first = (Token*)unit->first ();
66
Token *last = (Token*)unit->last ();
67
if (pos._pos == WeavePos::WP_BEFORE) {
68
_commander.move_before (first, last, tok);
71
_commander.move (first, last, tok);
105
// store the unit in the right order for insertion (later when committing)
107
pos._units.push_front(unit);
109
pos._units.push_back(unit);
75
// insert a generated string a given position
76
void WeaverBase::paste (const WeavePos &pos, const string &str) {
112
// the same as the other 'insert' method (above), but converts string to unit
113
void WeaverBase::insert (const WeavePos &pos, const string &str, bool before) {
77
114
// return immediately if the string to paste is empty
81
118
ACUnit *unit = new ACUnit (_err);
82
bool has_nl = (strstr (str.c_str (), "\n") != NULL);
119
bool has_nl = (str.find('\n') != string::npos);
84
121
_line_mgr.directive (*unit);
85
122
*unit << str.c_str ();
87
124
_line_mgr.directive (*unit, (Unit*)pos._token->belonging_to (), pos._token);
92
// insert a generated string at the beginning of a unit
93
// The implementation makes sure that all pasted tokens will appear after the
94
// transformation in front of tokens that were pasted ahead of the first token
95
void WeaverBase::paste_first (Unit *unit, const string &str) {
96
UnitTokenMap::iterator i = _start_token_map.find (unit);
97
Token *start_token = 0;
98
if (i != _start_token_map.end ()) {
99
start_token = i->second;
102
start_token = new Token; // just a marker token without text etc.
103
Token *first = (Token*)unit->first ();
104
if (unit == (Unit*)_primary_start->belonging_to ())
105
first = _primary_start;
106
start_token->location (first->location ());
108
marker.append (*start_token);
109
unit->move_before (first, marker);
110
_start_token_map.insert (UnitTokenMap::value_type (unit, start_token));
112
paste (weave_pos (start_token, WeavePos::WP_BEFORE), str);
115
// insert the contents of a generated unit at the end of the translation
117
void WeaverBase::paste_end (Unit *unit) {
119
// this is our position ...
120
const WeavePos &pos = weave_pos (_primary_end, WeavePos::WP_AFTER);
122
// return immediately if the there is a problem with macro manipulation
123
if (macro_problem (pos))
126
_commander.addBuffer (unit);
127
Token *first = (Token*)unit->first ();
128
Token *last = (Token*)unit->last ();
129
_commander.move (first, last, pos._token);
132
// insert a generated string at the end of the translation unit (with move)
133
void WeaverBase::paste_end (const string &str) {
134
// return immediately if the string to paste is empty
138
ACUnit *unit = new ACUnit (_err);
139
bool has_nl = (strstr (str.c_str (), "\n") != NULL);
141
_line_mgr.directive (*unit);
142
*unit << str.c_str ();
144
_line_mgr.directive (*unit, (Unit*)_primary_end->belonging_to (), _primary_end);
126
insert (pos, unit, before);
149
130
// replace the text between two positions with some new text
150
131
void WeaverBase::replace (const WeavePos &from, const WeavePos &to,
151
132
const string &str) {
156
// replace the text of a syntax tree with some new text
157
void WeaverBase::replace (CTree *node, const string &str) {
158
const WeavePos &from = weave_pos (node->token (), WeavePos::WP_BEFORE);
159
const WeavePos &to = weave_pos (node->end_token (), WeavePos::WP_AFTER);
160
replace (from, to, str);
163
138
// check whether two tokens are on the same line of the same unit
164
139
bool same_line (Token *t1, Token *t2, bool check_end_of_t1) {
171
146
return (l1 == l2);
174
// copy the text between two position to another location
175
void WeaverBase::copy (const WeavePos &from, const WeavePos &to,
176
const WeavePos &dest) {
177
assert (from._pos == WeavePos::WP_BEFORE);
178
assert (to._pos == WeavePos::WP_AFTER);
179
if (macro_problem (from) || macro_problem (to) || macro_problem (dest))
182
if (dest._pos == WeavePos::WP_BEFORE) {
184
ACUnit *unit = new ACUnit (_err);
185
_line_mgr.directive (*unit,
186
(Unit*)from._token->belonging_to (), from._token);
188
if (unit->empty ()) delete unit; else paste (dest, unit);
190
_commander.copy_before (from._token, to._token, dest._token);
192
ACUnit *unit = new ACUnit (_err);
193
_line_mgr.directive (*unit,
194
(Unit*)dest._token->belonging_to (), dest._token);
196
if (unit->empty ()) delete unit; else paste (dest, unit);
200
if (!same_line (from._token, to._token, false)) {
201
ACUnit *unit = new ACUnit (_err);
202
_line_mgr.directive (*unit,
203
(Unit*)dest._token->belonging_to (), dest._token);
205
if (unit->empty ()) delete unit; else paste (dest, unit);
207
_commander.copy (from._token, to._token, dest._token);
208
if (!same_line (dest._token, from._token, true)) {
209
ACUnit *unit = new ACUnit (_err);
210
_line_mgr.directive (*unit,
211
(Unit*)from._token->belonging_to (), from._token);
213
if (unit->empty ()) delete unit; else paste (dest, unit);
218
// copy the text of a syntax tree to another location
219
void WeaverBase::copy (CTree *node, const WeavePos &dest) {
220
const WeavePos &from = weave_pos (node->token (), WeavePos::WP_BEFORE);
221
const WeavePos &to = weave_pos (node->end_token (), WeavePos::WP_AFTER);
222
copy (from, to, dest);
225
150
// kill the text between two positions
226
151
void WeaverBase::kill (const WeavePos &from, const WeavePos &to) {
282
bool WeaverBase::kill_macro_problem (CTree *tree) {
283
Token *start = tree->token();
284
Token *end = tree->end_token();
285
if (start->unit () != end->unit())
287
if (start->unit()->isMacroExp ()) {
288
start = ((MacroUnit*)start->unit())->ExpansionBegin (start);
289
end = ((MacroUnit*)end->unit())->ExpansionEnd (end);
295
string WeaverBase::protection_string (CProtection::Type prot) {
297
case CProtection::PROT_PRIVATE: return "\nprivate:\n";
298
case CProtection::PROT_PROTECTED: return "\nprotected:\n";
299
case CProtection::PROT_PUBLIC: return "\npublic:\n";
306
bool WeaverBase::needs_this (CFunctionInfo *func)
308
// check if the called function is a method (needs a 'this' pointer)
309
if (func->isMethod () && !func->isStaticMethod ())
311
return !(func->isOperator () &&
312
(strcmp (func->Name (), "operator new") == 0 ||
313
strcmp (func->Name (), "operator new[]") == 0 ||
314
strcmp (func->Name (), "operator delete") == 0 ||
315
strcmp (func->Name (), "operator delete[]") == 0));
320
void WeaverBase::print_tree (ostream &out, CTree *node)
322
if (node->NodeName () == CT_Token::NodeId ())
323
out << node->token ()->text () << " ";
325
for (int s = 0; s < node->Sons (); s++)
326
print_tree (out, node->Son (s));
329
CClassInfo *WeaverBase::cscope(CObjectInfo *obj) {
330
CRecord *crec = obj->ClassScope ();
331
return crec ? crec->ClassInfo () : (CClassInfo*)0;
334
string WeaverBase::cleanup_name(const string& in) {
336
string::size_type pos = result.length ();
337
while ((pos = result.rfind ("::<unnamed>", pos)) != string::npos)
338
result = result.erase (pos, 11);
339
if (result.find ("<unnamed>") == 0)
340
result = result.erase (0, 9);
344
CScopeInfo *WeaverBase::nscope(CObjectInfo *obj) {
345
// template instances are stored in a special scope, better take the template
346
// if (obj->TemplateInstance ())
347
// obj = obj->TemplateInstance ()->Template ();
349
// functions that are only friend declarations of an assigned scope
350
CScopeInfo *assigned = obj->AssignedScope ();
352
return (assigned->GlobalScope () || assigned->isAnonymous ()) ? 0:assigned;
354
CRecord *crec = obj->ClassScope ();
355
CScopeInfo *qual = obj->QualifiedScope ();
356
CScopeInfo *scope = obj->Scope ();
357
return crec ? (CScopeInfo*)crec : (qual ? qual :
358
((scope->GlobalScope () || scope->isAnonymous ()) ? 0 : scope));
361
void WeaverBase::rename_args (CFunctionInfo *func, const char * new_name, vector<string> &arg_names) {
362
// first rename the arguments in the argument list
363
for (unsigned arg = 0; arg < func->Arguments (); arg++) {
364
if (func->Argument (arg)->isAnonymous()) {
367
name << new_name << arg;
368
// insert the generated name
369
rename (func->Argument (arg), name.str ());
370
arg_names.push_back (name.str ());
373
arg_names.push_back (func->Argument (arg)->Name ().c_str());
378
void WeaverBase::rename (CArgumentInfo *arg, const string &new_name) {
379
// don't change anything with void arguments
380
if (arg->TypeInfo ()->is_void ())
383
// find the syntax tree node of the argument name
384
CT_ArgDecl *arg_decl = (CT_ArgDecl*)arg->Tree ();
385
CT_Declarator *declarator = (CT_Declarator*)arg_decl->Declarator ();
386
CT_SimpleName *arg_name = name (declarator);
388
if (arg_name->NodeName () != CT_PrivateName::NodeId ()) {
389
replace (arg_name, new_name);
392
// in the case of an anonymous argument I have to find an insert pos
393
CTree *left = 0, *right = 0;
395
if (declarator->NodeName () == CT_InitDeclarator::NodeId ())
396
right = ((CT_InitDeclarator*)declarator)->Initializer ();
397
else if (declarator->NodeName () == CT_BracedDeclarator::NodeId ())
398
right = declarator->Son (declarator->Sons () - 1);
399
else if (declarator->NodeName () == CT_ArrayDeclarator::NodeId ())
400
right = declarator->Son (1);
401
else if (declarator->NodeName () == CT_FctDeclarator::NodeId ())
402
right = declarator->Son (1);
403
else if (declarator->NodeName () == CT_RefDeclarator::NodeId ())
404
left = declarator->Son (0);
405
else if (declarator->NodeName () == CT_PtrDeclarator::NodeId ())
406
left = declarator->Son (declarator->Sons () - 2);
407
else if (declarator->NodeName () == CT_MembPtrDeclarator::NodeId ())
408
left = declarator->Son (declarator->Sons () - 2);
409
else if (declarator->NodeName () == CT_BitFieldDeclarator::NodeId ())
410
right = declarator->Son (1);
412
_err << sev_fatal << declarator->token ()->location ()
413
<< "unknown declarator type" << endMessage;
417
if (!left && !right) {
418
// no declarator + anonymous => there must be at least a decl spec seq!
419
left = arg_decl->DeclSpecs ();
422
const WeavePos &lp = weave_pos (left->end_token (), WeavePos::WP_AFTER);
423
paste (lp, new_name);
427
const WeavePos &rp = weave_pos (right->token (), WeavePos::WP_BEFORE);
429
paste (rp, new_name);
432
_err << sev_fatal << declarator->token ()->location ()
433
<< "found no hook to replace ananymous arg name" << endMessage;
437
CT_SimpleName *WeaverBase::is_name (CTree *node) {
438
if (node->NodeName () == CT_QualName::NodeId () ||
439
node->NodeName () == CT_SimpleName::NodeId () ||
440
node->NodeName () == CT_OperatorName::NodeId () ||
441
node->NodeName () == CT_ConversionName::NodeId () ||
442
node->NodeName () == CT_RootQualName::NodeId () ||
443
node->NodeName () == CT_PrivateName::NodeId ())
444
return (CT_SimpleName*)node;
446
return (CT_SimpleName*)0;
449
CT_FctDeclarator *WeaverBase::fct_declarator (CT_Declarator *declarator) {
451
CT_Declarator *next = (CT_Declarator*)declarator->Declarator ();
452
if (declarator->NodeName () == CT_FctDeclarator::NodeId () &&
454
return (CT_FctDeclarator*)declarator;
456
} while (!is_name (declarator));
457
return (CT_FctDeclarator*)0;
460
CT_SimpleName *WeaverBase::name (CT_Declarator *&declarator) {
461
CTree *node = declarator;
462
declarator = (CT_Declarator*)0;
463
while (!is_name (node)) {
464
declarator = (CT_Declarator*)node;
465
node = declarator->Declarator ();
468
return (CT_SimpleName*)node;
471
// return LinkageSpec node for extern "C" <decl> like declarations
472
CTree *WeaverBase::linkage_adjust (CT_Decl *decl) {
473
CT_LinkageSpec *linkage = decl->Linkage ();
474
return (!linkage || linkage->isList ()) ? decl : linkage;
219
int WeaverBase::primary_len() const {
220
return _primary_end->location().line() - _primary_start->location().line() + 1;