~ubuntu-branches/ubuntu/natty/aspectc++/natty

« back to all changes in this revision

Viewing changes to AspectC++/WeaverBase.cc

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2005-12-23 10:49:40 UTC
  • Revision ID: james.westby@ubuntu.com-20051223104940-ig4klhoi991zs7km
Tags: upstream-0.99+1.0pre2
ImportĀ upstreamĀ versionĀ 0.99+1.0pre2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// This file is part of the AspectC++ compiler 'ac++'.
 
2
// Copyright (C) 1999-2003  The 'ac++' developers (see aspectc.org)
 
3
//                                                                
 
4
// This program is free software;  you can redistribute it and/or 
 
5
// modify it under the terms of the GNU General Public License as 
 
6
// published by the Free Software Foundation; either version 2 of 
 
7
// the License, or (at your option) any later version.            
 
8
//                                                                
 
9
// This program is distributed in the hope that it will be useful,
 
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
 
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
 
12
// GNU General Public License for more details.                   
 
13
//                                                                
 
14
// You should have received a copy of the GNU General Public      
 
15
// License along with this program; if not, write to the Free     
 
16
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
 
17
// MA  02111-1307  USA                                            
 
18
 
 
19
// AspectC++ includes
 
20
#include "WeaverBase.h"
 
21
#include "ACUnit.h"
 
22
#include "LineDirectiveMgr.h"
 
23
 
 
24
// PUMA includes
 
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
#include "Puma/CTree.h"
 
32
#include "Puma/MacroUnit.h"
 
33
 
 
34
// C++ includes
 
35
#include <sstream>
 
36
using std::stringstream;
 
37
using std::endl;
 
38
using std::ends;
 
39
#include <cstring>
 
40
using std::strstr;
 
41
 
 
42
const WeavePos &WeaverBase::weave_pos (Token *t, WeavePos::Pos p) {
 
43
 
 
44
  // try to insert the position as a new one
 
45
  pair<WPSet::iterator, bool> result = _positions.insert (WeavePos (t, p));
 
46
 
 
47
  // the resulting iterator points either to the new or an existing entry
 
48
  return *result.first;
 
49
}
 
50
 
 
51
// insert the contents of a generated unit at a given position (with move)
 
52
void WeaverBase::paste (const WeavePos &pos, Unit *unit) {
 
53
  // return immediately if the there is a problem with macro manipulation
 
54
  if (macro_problem (pos))
 
55
    return;
 
56
    
 
57
  _commander.addBuffer (unit);
 
58
  Token *first = (Token*)unit->first ();
 
59
  Token *last  = (Token*)unit->last ();
 
60
  if (pos._pos == WeavePos::WP_BEFORE) {
 
61
    _commander.move_before (first, last, pos._token);
 
62
  }
 
63
  else {
 
64
    _commander.move (first, last, pos._token);
 
65
  }
 
66
}
 
67
 
 
68
// insert a generated string a given position
 
69
void WeaverBase::paste (const WeavePos &pos, const string &str) {
 
70
  // return immediately if the string to paste is empty
 
71
  if (str == "")
 
72
    return;
 
73
  
 
74
  ACUnit *unit = new ACUnit (_err);
 
75
  bool has_nl = (strstr (str.c_str (), "\n") != NULL);
 
76
  if (has_nl)
 
77
    _line_mgr.directive (*unit);
 
78
  *unit << str.c_str ();
 
79
  if (has_nl)
 
80
    _line_mgr.directive (*unit, (Unit*)pos._token->belonging_to (), pos._token);
 
81
  *unit << endu;
 
82
  paste (pos, unit);
 
83
}
 
84
 
 
85
// replace the text between two positions with some new text
 
86
void WeaverBase::replace (const WeavePos &from, const WeavePos &to,
 
87
                                             const string &str) {
 
88
  paste (from, str);
 
89
  kill (from, to);
 
90
}
 
91
 
 
92
// replace the text of a syntax tree with some new text
 
93
void WeaverBase::replace (CTree *node, const string &str) {
 
94
  const WeavePos &from = weave_pos (node->token (), WeavePos::WP_BEFORE);
 
95
  const WeavePos &to   = weave_pos (node->end_token (), WeavePos::WP_AFTER);
 
96
  replace (from, to, str);
 
97
}
 
98
 
 
99
// copy the text between two position to another location
 
100
void WeaverBase::copy (const WeavePos &from, const WeavePos &to, 
 
101
                       const WeavePos &dest) {
 
102
  assert (from._pos == WeavePos::WP_BEFORE);
 
103
  assert (to._pos == WeavePos::WP_AFTER);
 
104
  if (macro_problem (from) || macro_problem (to) || macro_problem (dest))
 
105
    return;
 
106
    
 
107
  if (dest._pos == WeavePos::WP_BEFORE) {
 
108
    _line_mgr.insert ((Unit*)dest._token->belonging_to (), dest._token);
 
109
    _commander.copy_before (from._token, to._token, dest._token);
 
110
    _line_mgr.insert ((Unit*)dest._token->belonging_to (), dest._token);
 
111
  }
 
112
  else {
 
113
    _line_mgr.insert ((Unit*)dest._token->belonging_to (), dest._token, true);
 
114
    _commander.copy (from._token, to._token, dest._token);  }
 
115
    _line_mgr.insert ((Unit*)dest._token->belonging_to (), dest._token, true);
 
116
}
 
117
  
 
118
// copy the text of a syntax tree to another location
 
119
void WeaverBase::copy (CTree *node, const WeavePos &dest) {
 
120
  const WeavePos &from = weave_pos (node->token (), WeavePos::WP_BEFORE);
 
121
  const WeavePos &to   = weave_pos (node->end_token (), WeavePos::WP_AFTER);
 
122
  copy (from, to, dest);
 
123
}
 
124
 
 
125
// kill the text between two positions
 
126
void WeaverBase::kill (const WeavePos &from, const WeavePos &to) {
 
127
  // TODO: this should not matter, the code shoud be able to deal with it
 
128
  assert (from._pos == WeavePos::WP_BEFORE);
 
129
  assert (to._pos == WeavePos::WP_AFTER);
 
130
  if (macro_problem (from) || macro_problem (to))
 
131
    return;
 
132
    
 
133
  bool has_nl = (strstr (from._token->text ().c_str (), "\n") != NULL);
 
134
  if (to._token && from._token != to._token || has_nl)
 
135
    _line_mgr.insert ((Unit*)to._token->belonging_to (), to._token, true);
 
136
  _commander.kill (from._token, to._token);
 
137
}
 
138
  
 
139
// kill the text of a syntax tree
 
140
void WeaverBase::kill (CTree *node) {
 
141
  const WeavePos &from = weave_pos (node->token (), WeavePos::WP_BEFORE);
 
142
  const WeavePos &to   = weave_pos (node->end_token (), WeavePos::WP_AFTER);
 
143
  kill (from, to);
 
144
}
 
145
 
 
146
bool WeaverBase::commit ()
 
147
 {
 
148
   ManipError terror = _commander.valid ();
 
149
   if (!terror)
 
150
      _commander.commit ();
 
151
   else
 
152
      _err << terror << endMessage;
 
153
   return (bool)terror;
 
154
 }
 
155
 
 
156
bool WeaverBase::macro_problem (const WeavePos &pos) {
 
157
  Token *token = pos._token;
 
158
  Unit  *unit  = (Unit*)token->belonging_to ();
 
159
  assert (unit);
 
160
  if (unit->isMacroExp () &&
 
161
      ((pos._pos == WeavePos::WP_BEFORE &&
 
162
        unit->isMacroExp () && !((MacroUnit*)unit)->ExpansionBegin (token)) ||
 
163
       (pos._pos == WeavePos::WP_AFTER &&
 
164
           unit->isMacroExp () && !((MacroUnit*)unit)->ExpansionEnd (token)))) {
 
165
      _err << sev_warning << token->location ()
 
166
           << "transformation within macro '"
 
167
           << ((MacroUnit*)unit)->MacroBegin ()->text () << "'" << endMessage;
 
168
      return true;
 
169
  }
 
170
  return false;  
 
171
}
 
172
 
 
173
string WeaverBase::protection_string (CProtection::Type prot) {
 
174
  switch (prot) {
 
175
  case CProtection::PROT_PRIVATE:   return "\nprivate:\n";
 
176
  case CProtection::PROT_PROTECTED: return "\nprotected:\n";
 
177
  case CProtection::PROT_PUBLIC:    return "\npublic:\n";
 
178
  default:
 
179
    assert (false);
 
180
    return "";
 
181
  }
 
182
}
 
183
 
 
184
bool WeaverBase::needs_this (CFunctionInfo *func)
 
185
 {
 
186
  // check if the called function is a method (needs a 'this' pointer)
 
187
  if (func->isMethod () && !func->isStaticMethod ())
 
188
   {
 
189
     return !(func->isOperator () &&
 
190
              (strcmp (func->Name (), "operator new") == 0 ||
 
191
               strcmp (func->Name (), "operator new[]") == 0 ||
 
192
               strcmp (func->Name (), "operator delete") == 0 ||
 
193
               strcmp (func->Name (), "operator delete[]") == 0));
 
194
   }
 
195
  return false;
 
196
 }
 
197
 
 
198
void WeaverBase::print_tree (ostream &out, CTree *node)
 
199
 {
 
200
   if (node->NodeName () == CT_Token::NodeId ())
 
201
     out << node->token ()->text () << " ";
 
202
   else
 
203
      for (int s = 0; s < node->Sons (); s++)
 
204
         print_tree (out, node->Son (s));
 
205
 }
 
206
 
 
207
CClassInfo *WeaverBase::cscope(CObjectInfo *obj) {
 
208
  CRecord *crec = obj->ClassScope ();
 
209
  return crec ? crec->ClassInfo () : (CClassInfo*)0;
 
210
}
 
211
 
 
212
CScopeInfo *WeaverBase::nscope(CObjectInfo *obj) {
 
213
  // template instances are stored in a special scope, better take the template
 
214
  if (obj->TemplateInstance ())
 
215
    obj = obj->TemplateInstance ()->Template ();
 
216
    
 
217
  // functions that are only friend declarations of an assigned scope
 
218
  CScopeInfo *assigned = obj->AssignedScope ();
 
219
  if (assigned)
 
220
    return (assigned->GlobalScope () || assigned->isAnonymous ()) ? 0:assigned;
 
221
 
 
222
  CRecord *crec = obj->ClassScope ();
 
223
  CScopeInfo *qual = obj->QualifiedScope ();
 
224
  CScopeInfo *scope = obj->Scope ();
 
225
  return crec ? (CScopeInfo*)crec : (qual ? qual :
 
226
    ((scope->GlobalScope () || scope->isAnonymous ()) ? 0 : scope));
 
227
}
 
228
 
 
229
void WeaverBase::rename_args (CFunctionInfo *func, const char * new_name) {
 
230
  // first rename the arguments in the argument list  
 
231
  for (unsigned arg = 0; arg < func->Arguments (); arg++)
 
232
    rename (func->Argument (arg), new_name, arg);
 
233
 
 
234
  // now rename the argument references in the constructor initialization list
 
235
  if (func->isConstructor () && func->Tree ()) {
 
236
    CTree *init = ((CT_FctDef*)func->Tree ())->CtorInit ();
 
237
    if (init) {
 
238
      for (unsigned arg = 0; arg < func->Arguments (); arg++)
 
239
        rename_simple_name (func->Argument (arg), new_name, arg, init);
 
240
    }
 
241
  }
 
242
}
 
243
 
 
244
void WeaverBase::rename (CArgumentInfo *arg, const string &new_name, int app) {
 
245
  // don't change anything with void arguments
 
246
  if (arg->TypeInfo ()->is_void ())
 
247
    return;
 
248
    
 
249
  // find the syntax tree node of the argument name
 
250
  CT_ArgDecl *arg_decl = (CT_ArgDecl*)arg->Tree ();
 
251
  CT_Declarator *declarator = (CT_Declarator*)arg_decl->Declarator ();
 
252
  CT_SimpleName *arg_name = name (declarator);
 
253
 
 
254
  // create the new name
 
255
  ostringstream name;
 
256
  name << " " << new_name; 
 
257
  if (app >= 0) // append an index to the name?
 
258
    name << app;
 
259
  name << ends;
 
260
 
 
261
  if (arg_name->NodeName () != CT_PrivateName::NodeId ()) {
 
262
    replace (arg_name, name.str ());
 
263
  }
 
264
  else {
 
265
    // in the case of an anonymous argument I have to find an insert pos
 
266
    CTree *left = 0, *right = 0;
 
267
    if (declarator) {
 
268
      if (declarator->NodeName () == CT_InitDeclarator::NodeId ())
 
269
        right = ((CT_InitDeclarator*)declarator)->Initializer ();
 
270
      else if (declarator->NodeName () == CT_BracedDeclarator::NodeId ())
 
271
        right = declarator->Son (declarator->Sons () - 1);
 
272
      else if (declarator->NodeName () == CT_ArrayDeclarator::NodeId ())
 
273
        right = declarator->Son (1);
 
274
      else if (declarator->NodeName () == CT_FctDeclarator::NodeId ())
 
275
        right = declarator->Son (1);
 
276
      else if (declarator->NodeName () == CT_RefDeclarator::NodeId ())
 
277
        left = declarator->Son (0);
 
278
      else if (declarator->NodeName () == CT_PtrDeclarator::NodeId ())
 
279
        left = declarator->Son (declarator->Sons () - 2);
 
280
      else if (declarator->NodeName () == CT_MembPtrDeclarator::NodeId ())
 
281
        left = declarator->Son (declarator->Sons () - 2);
 
282
      else if (declarator->NodeName () == CT_BitFieldDeclarator::NodeId ())
 
283
        right = declarator->Son (1);
 
284
      else {
 
285
        _err << sev_fatal << declarator->token ()->location ()
 
286
             << "unknown declarator type" << endMessage;
 
287
        return;
 
288
      }
 
289
    }
 
290
    if (!left && !right) {
 
291
      // no declarator + anonymous => there must be at least a decl spec seq!
 
292
      left = arg_decl->DeclSpecs ();
 
293
    }
 
294
    if (left) {
 
295
      const WeavePos &lp = weave_pos (left->end_token (), WeavePos::WP_AFTER);
 
296
      paste (lp, name.str ());
 
297
    }
 
298
    else if (right) {
 
299
      const WeavePos &rp = weave_pos (right->token (), WeavePos::WP_BEFORE);
 
300
      paste (rp, name.str ());
 
301
    }
 
302
    else
 
303
      _err << sev_fatal << declarator->token ()->location ()
 
304
           << "found no hook to replace ananymous arg name" << endMessage;
 
305
  }
 
306
}
 
307
 
 
308
void WeaverBase::rename_simple_name (CObjectInfo *renamed_obj,
 
309
                                      const char *new_name, int app,
 
310
                                      CTree *node) {
 
311
  const char *nodename = node->NodeName ();
 
312
  if (nodename == CT_SimpleName::NodeId ()) {
 
313
    CObjectInfo *obj = ((CT_SimpleName*)node)->Object ();
 
314
    if (obj == renamed_obj) {
 
315
      // create a unit with the new name
 
316
      ACUnit *name_unit = new ACUnit (_err); 
 
317
      _commander.addBuffer (name_unit);
 
318
      *name_unit << new_name;
 
319
      if (app >= 0) // append an index to the name?
 
320
        *name_unit << app;
 
321
      *name_unit << endu;
 
322
 
 
323
      // replace the token with the generated name
 
324
      _commander.replace (node->token (), node->end_token (),
 
325
        (Token*)name_unit->first (), (Token*)name_unit->last ());
 
326
    }
 
327
  }
 
328
 
 
329
  for (int s = 0; s < node->Sons (); s++)
 
330
    rename_simple_name (renamed_obj, new_name, app, node->Son (s));
 
331
}   
 
332
 
 
333
CT_SimpleName *WeaverBase::is_name (CTree *node) {
 
334
  if (node->NodeName () == CT_QualName::NodeId () ||
 
335
      node->NodeName () == CT_SimpleName::NodeId () ||
 
336
      node->NodeName () == CT_OperatorName::NodeId () ||
 
337
      node->NodeName () == CT_ConversionName::NodeId () ||
 
338
      node->NodeName () == CT_RootQualName::NodeId () ||
 
339
      node->NodeName () == CT_PrivateName::NodeId ())
 
340
    return (CT_SimpleName*)node;
 
341
  else
 
342
    return (CT_SimpleName*)0;
 
343
}
 
344
 
 
345
CT_FctDeclarator *WeaverBase::fct_declarator (CT_Declarator *declarator) {
 
346
  do {
 
347
    CT_Declarator *next = (CT_Declarator*)declarator->Declarator ();
 
348
    if (declarator->NodeName () == CT_FctDeclarator::NodeId () &&
 
349
        is_name (next))
 
350
      return (CT_FctDeclarator*)declarator;
 
351
    declarator = next;
 
352
  } while (!is_name (declarator));
 
353
  return (CT_FctDeclarator*)0;
 
354
}
 
355
 
 
356
CT_SimpleName *WeaverBase::name (CT_Declarator *&declarator) {
 
357
  CTree *node = declarator;
 
358
  declarator  = (CT_Declarator*)0;
 
359
  while (!is_name (node)) {
 
360
    declarator = (CT_Declarator*)node;
 
361
    node = declarator->Declarator ();
 
362
  }
 
363
      
 
364
  return (CT_SimpleName*)node;
 
365
}
 
366
 
 
367
// return LinkageSpec node for extern "C" <decl> like declarations
 
368
CTree *WeaverBase::linkage_adjust (CT_Decl *decl) {
 
369
  CT_LinkageSpec *linkage = decl->Linkage ();
 
370
  return (!linkage || linkage->isList ()) ? decl : linkage;
 
371
}