~ubuntu-branches/ubuntu/maverick/aspectc++/maverick

« back to all changes in this revision

Viewing changes to AspectC++/Transformer.cc

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-04-10 17:40:52 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080410174052-xdnsm7oi8hauyyf1
Tags: 1.0pre4~svn.20080409+dfsg-3
Fix another missing include, this time in Ag++/StdSystem.cc

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#include "Transformer.h"
21
21
#include "JPAdvice.h"
22
22
#include "PointCutEvaluator.h"
23
 
#include "MemberProtections.h"
24
23
#include "PointCut.h"
25
24
#include "PointCutContext.h"
26
 
#include "IntroductionInfo.h"
 
25
#include "OrderInfo.h"
27
26
#include "AdviceInfo.h"
28
27
#include "AspectInfo.h"
 
28
#include "IntroductionInfo.h"
29
29
#include "JoinPointPlan.h"
30
30
#include "Plan.h"
31
31
#include "Repository.h"
34
34
#include "BackEndProblems.h"
35
35
#include "ACConfig.h"
36
36
#include "Introducer.h"
 
37
#include "IncludeGraph.h"
 
38
#include "PointCutExpr.h"
 
39
#include "ModelBuilder.h"
 
40
#include "IntroductionUnit.h"
37
41
 
38
42
// PUMA includes
39
43
#include "Puma/CProject.h"
44
48
#include "Puma/CTranslationUnit.h"
45
49
#include "Puma/CClassDatabase.h"
46
50
#include "Puma/ACAspectInfo.h"
 
51
#include "Puma/ACAdviceInfo.h"
47
52
#include "Puma/ACIntroductionInfo.h"
48
53
#include "Puma/ACPointcutInfo.h"
49
54
#include "Puma/ACTree.h"
50
55
#include "Puma/CPrintVisitor.h"
 
56
#include "Puma/SysCall.h"
51
57
 
52
58
// C++ includes
53
59
#include <sstream>
54
60
using std::stringstream;
55
61
using std::endl;
56
 
using std::ends;
 
62
#include <stdlib.h> // for getenv
 
63
#ifdef _MSC_VER
 
64
#include <io.h>
 
65
#else
 
66
#include <unistd.h> // for access()!
 
67
#endif // _MSC_VER
 
68
#include <fcntl.h>
57
69
 
58
70
void Transformer::work (Unit *unit, Token *primary_start, Token *primary_end) {
59
71
 
60
72
  // set the start and end token of the unit
61
 
  _primary_start = primary_start;
62
 
  _primary_end   = primary_end;
 
73
  _code_weaver.init (primary_start, primary_end);
63
74
  
64
75
  // determine back-end compiler problems and setup code weaver
65
76
  BackEndProblems back_end_problems;
66
 
  back_end_problems._local_class     = _conf.problem_local_class ();
67
 
  back_end_problems._spec_scope      = _conf.problem_spec_scope ();
68
 
  back_end_problems._size_type       = _conf.size_type ();
69
 
  back_end_problems._warn_macro      = _conf.warn_macro();
70
 
  back_end_problems._warn_deprecated = _conf.warn_deprecated();
 
77
  back_end_problems._local_class       = _conf.problem_local_class ();
 
78
  back_end_problems._spec_scope        = _conf.problem_spec_scope ();
 
79
  back_end_problems._use_always_inline = !_conf.problem_force_inline ();
 
80
  back_end_problems._size_type         = _conf.size_type ();
 
81
  back_end_problems._warn_macro        = _conf.warn_macro();
 
82
  back_end_problems._warn_deprecated   = _conf.warn_deprecated();
71
83
  _code_weaver.problems (back_end_problems);
72
84
  
73
85
  // perform the transformation
74
86
  CTranslationUnit *tunit1 = 0;
75
 
  PointCutContext *context1 = 0;
76
 
  Plan plan (_err);
 
87
  ModelBuilder jpm (_vm, _err, _conf);
77
88
  
78
 
  bool ok = (phase1 (unit, tunit1, context1, plan) &&
79
 
             phase2 (unit, tunit1, *context1, plan));
 
89
  bool ok = (phase1 (unit, tunit1, jpm) &&
 
90
             phase2 (unit, tunit1, jpm));
80
91
  if (tunit1)
81
92
    delete tunit1;
82
 
  if (context1)
83
 
    delete context1;
84
93
  if (!ok)
85
94
    _vm << "Aborting" << endvm;
86
95
}
87
96
 
88
97
bool Transformer::phase1 (Unit *unit, CTranslationUnit *&tunit,
89
 
                          PointCutContext *&context, Plan &plan) {
 
98
                          ModelBuilder &jpm) {
90
99
 
91
100
  _vm << "Inserting namespace AC" << endvm;
92
101
  // in front of start!
115
124
  //    printer.print (tunit->tree (), cout);
116
125
  //    tunit->db ().Dump (cout, 2);
117
126
  
118
 
  context = new PointCutContext (*tunit);
 
127
  // create the phase 1 join point model
 
128
  _vm << "Setting up join point model 1 ..." << endvm;
 
129
  _vm++;
 
130
  jpm.setup_phase1 (*tunit);
 
131
  _vm--;
119
132
  
 
133
  // set up the project repository
120
134
  _repo.setup (unit);
121
135
 
122
136
  _vm << "Setting Aspect Access Priviledges ..." << endvm;
123
 
  aspect_priviledges (*tunit);
 
137
  aspect_priviledges (jpm);
124
138
  
125
139
  _vm << "Weaving Introductions ..." << endvm;
126
 
  introductions (*tunit, *context, plan);
 
140
  introductions (*tunit, jpm);
127
141
      
128
142
  _vm << "Weaving Advice Declarations ..." << endvm;
129
143
  advice (*tunit);
131
145
  _vm << "Weaving Singleton Aspects ..." << endvm;
132
146
  singleton_aspects (*tunit);
133
147
 
134
 
  _vm << "Slice/Intro Includes ..." << endvm;
135
 
  _code_weaver.slice_includes (_project, _primary_start);
 
148
//  _vm << "Slice/Intro Includes ..." << endvm;
 
149
//  _code_weaver.slice_includes (_project, _primary_start);
136
150
 
137
151
  _vm << "Commiting" << endvm;
138
152
  _code_weaver.commit ();
146
160
}
147
161
 
148
162
bool Transformer::phase2 (Unit *unit, CTranslationUnit *tunit1,
149
 
                          PointCutContext &context1, Plan &plan1) {
 
163
                          ModelBuilder &jpm) {
 
164
 
 
165
  IncludeGraph ig (_project);
 
166
  ig.init (*tunit1);
 
167
//  ig.dump ();
 
168
  
 
169
  _vm << "Preparing introductions ..." << endvm;
 
170
  Plan plan (_err, jpm);
 
171
 
 
172
  // get all aspects from the plan (in some order)
 
173
  const Plan::AspectContainer &aspects = plan.aspect_infos ();
 
174
  for (Plan::AspectContainer::const_iterator i = aspects.begin ();
 
175
    i != aspects.end (); ++i) {
 
176
      
 
177
    JPL_Aspect &jpl_aspect = i->loc ();
 
178
 
 
179
    // add introductions to plan
 
180
    list<JPL_Introduction*> intros;
 
181
    jpl_aspect.collect_intros (intros);
 
182
    
 
183
    for (list<JPL_Introduction*>::iterator i = intros.begin ();
 
184
      i != intros.end (); ++i) {
 
185
      IntroductionInfo *ii = plan.addIntroduction (jpl_aspect, **i);
 
186
      ii->analyze_expr (_err, jpm);
 
187
    }
 
188
 
 
189
    // add order advices to plan
 
190
    list<JPL_Order*> orders;
 
191
    jpl_aspect.collect_orders (orders);
 
192
    
 
193
    for (list<JPL_Order*>::iterator i = orders.begin ();
 
194
      i != orders.end (); ++i) {
 
195
      OrderInfo *oi = plan.addOrder (jpl_aspect, **i);
 
196
      oi->analyze_exprs (_err, jpm);
 
197
      if (!getenv ("ACNEWREPO")) {
 
198
        _repo.update (*oi);
 
199
      }
 
200
    }
 
201
  }
150
202
 
151
203
  _vm << "Parsing again ..." << endvm;
152
204
  
153
205
  // parse the translation unit, but ignore function bodies
154
 
  Introducer introducer (_code_weaver, _parser, plan1);
 
206
  Introducer introducer (plan, _code_weaver, _parser, jpm, ig);
155
207
  _parser.introducer (&introducer);
156
208
  CTranslationUnit *tunit = _parser.parse (*unit, _project);
157
209
  _parser.introducer (0);
158
210
 
159
211
  // do semantic analysis of expressions
160
212
  _sem_visitor.run (tunit->tree ());
 
213
  list<CTree*> &ah_trees = introducer.ah_trees ();
 
214
  for (list<CTree*>::iterator i = ah_trees.begin (); i != ah_trees.end (); ++i)
 
215
    if (*i)
 
216
      _sem_visitor.run (*i);
161
217
 
162
218
  if (_err.severity () >= sev_error) {
163
219
    // TODO: delete takes too much time and has no real use for ac++
174
230
  //    CPrintVisitor printer;
175
231
  //    printer.print (tunit->tree (), cout);
176
232
  
177
 
  PointCutContext context (*tunit);
 
233
  _vm << "Updating repository intro part" << endvm;
 
234
  if (!getenv ("ACNEWREPO")) {
 
235
    update_intros_in_repo (jpm);
 
236
  }
 
237
  
 
238
  jpm.setup_phase2 (*tunit, ah_trees);
178
239
  
179
240
  _vm << "Weaving Join Points ..." << endvm;
180
 
  join_points (*tunit, context);
 
241
  Plan plan2 (_err, jpm);
 
242
  join_points (*tunit, jpm, plan2);
181
243
      
182
244
  _vm << "Final cleanup" << endvm;
183
245
  cleanup (*tunit);
 
246
 
 
247
  if (_conf.dynamic ()) {
 
248
    _vm << "Preparing for dynamic weaving" << endvm;
 
249
    prepare_dynamic_weaving (jpm);  
 
250
  }
 
251
 
 
252
  // generate a string with aspect header include directives
 
253
  determine_aspect_includes (ig);
184
254
  
185
255
  _vm << "Commiting" << endvm;
186
256
  _code_weaver.commit ();
190
260
  // delete tunit;
191
261
  
192
262
  _repo.cleanup ();
 
263
 
193
264
  return (_err.severity () < sev_error);
194
265
}
195
266
 
196
 
 
197
 
void Transformer::aspect_priviledges (CTranslationUnit &tunit) {
198
 
  CClassDatabase &db = tunit.db ();
 
267
void Transformer::determine_aspect_includes (const IncludeGraph &ig) {
 
268
  // find all files that are included by aspect headers
 
269
  if (_conf.iterate_aspects ()) {
 
270
    // collect the names of aspect header files,
 
271
    // generate a unit with include statements for these files,
 
272
    PathIterator ah_iter (".*\\.ah$");
 
273
    while (_project.iterate (ah_iter))
 
274
      _aspect_includes += aspect_include_cluster (ah_iter.file (), ig);
 
275
  }
 
276
  else {
 
277
    // Get the names from the configuration object (-a options)
 
278
    for (int i = 0; i < _conf.aspect_headers (); i++)
 
279
      _aspect_includes += aspect_include_cluster (_conf.aspect_header (i), ig);
 
280
  }
 
281
}
 
282
 
 
283
string Transformer::aspect_include_cluster (const char* ah_file,
 
284
  const IncludeGraph &ig) {
 
285
 
 
286
  // find the corresponding unit object for the aspect header file name
 
287
  const Unit *unit = _project.unitManager ().getUnit (ah_file, true);
 
288
  if (!unit || !unit->isFile ()) {
 
289
    _err << sev_fatal << "Unit for \"" << ah_file << "\" not found or no file."
 
290
         << endMessage;
 
291
    return "";
 
292
  }
 
293
 
 
294
  // determine the aspect header cluster for this aspect header unit
 
295
  set<const Unit*> cluster_units;
 
296
  determine_aspect_cluster (unit, ig, cluster_units);
 
297
  
 
298
  // generate the code
 
299
  stringstream cluster;
 
300
  cluster << "#ifdef __ac_need_";
 
301
  Naming::mangle_file (cluster, (FileUnit*)unit);
 
302
  cluster << endl;
 
303
 
 
304
  for (set<const Unit*>::iterator i = cluster_units.begin ();
 
305
    i != cluster_units.end (); ++i) {
 
306
    const Unit *aspect_unit = *i;  
 
307
    Filename incname = _project.getInclString (aspect_unit->name ());
 
308
    cluster << "#ifndef __ac_have_";
 
309
    Naming::mangle_file (cluster, (FileUnit*)aspect_unit);
 
310
    cluster << endl;
 
311
    cluster << "#define __ac_have_";
 
312
    Naming::mangle_file (cluster, (FileUnit*)aspect_unit);
 
313
    cluster << endl;
 
314
    cluster << "#include \"" << incname << "\"" << endl;
 
315
    cluster << "#endif" << endl;
 
316
  }  
 
317
  
 
318
  cluster << "#endif" << endl;
 
319
  return cluster.str ();
 
320
}
 
321
 
 
322
void Transformer::determine_aspect_cluster (const Unit* ah_unit,
 
323
  const IncludeGraph &ig, set<const Unit*> &cluster) {
 
324
  
 
325
  // if the ah file is already a cluster member, we return immediately
 
326
  if (cluster.find (ah_unit) != cluster.end ())
 
327
    return;
 
328
 
 
329
  // otherwise the unit will be inserted
 
330
  cluster.insert (ah_unit);
 
331
      
 
332
  // find all header files that are included by this aspect header
 
333
  set<const Unit*> inc_units;
 
334
  ig.included_files (ah_unit, inc_units);
 
335
  
 
336
  // include all aspect headers that affect join points in these headers
 
337
  AspectIncludes &ais = _code_weaver.aspect_includes ();
 
338
  for (set<const Unit*>::iterator i = inc_units.begin ();
 
339
    i != inc_units.end (); ++i) {
 
340
    Unit *inc_unit = (Unit*)*i;
 
341
    AspectIncludes::const_iterator aii = ais.find (inc_unit);
 
342
    if (aii != ais.end ()) {
 
343
      const set<AspectRef> &aspect_refs = aii->second;
 
344
      for (set<AspectRef>::const_iterator ari = aspect_refs.begin ();
 
345
        ari != aspect_refs.end (); ++ari) {
 
346
        JPL_Aspect &jpl_aspect = ari->_aspect->loc ();
 
347
        Unit *aspect_unit = TI_Aspect::of (jpl_aspect)->unit ();
 
348
        // recursively analyze the cluster of this aspect header unit
 
349
        determine_aspect_cluster (aspect_unit, ig, cluster);
 
350
      }
 
351
    }
 
352
  }
 
353
}
 
354
 
 
355
void Transformer::prepare_dynamic_weaving (ModelBuilder &jpm) {
 
356
 
 
357
  // mark all operations that access introduced attributes
 
358
  const list<AccessInfo> &access_infos = jpm.access_infos ();
 
359
  for (list<AccessInfo>::const_iterator i = access_infos.begin ();
 
360
    i != access_infos.end (); ++i) {
 
361
    if (i->_info->isStatic () || i->_info->isAnonymous ())
 
362
      continue;
 
363
    Unit *unit = (Unit*)i->_info->Tree ()->token ()->belonging_to ();
 
364
    while (unit->isMacroExp ())
 
365
      unit = ((MacroUnit*)unit)->CallingUnit ();
 
366
    if (IntroductionUnit::cast (unit)) {
 
367
      Token *tok_before = i->_tree->token ();
 
368
      const WeavePos &before = _code_weaver.weave_pos (tok_before, WeavePos::WP_BEFORE);
 
369
      _code_weaver.paste (before, string ("/*** +access ") +
 
370
        string (i->_info->QualName ()) + string (" ***/\n"));      
 
371
      Token *tok_after = i->_tree->end_token ();
 
372
      const WeavePos &after = _code_weaver.weave_pos (tok_after, WeavePos::WP_AFTER);
 
373
      _code_weaver.paste (after, string ("/*** -access ") +
 
374
        string (i->_info->QualName ()) + string (" ***/\n"));      
 
375
      if (i->_tree->NodeName () == CT_MembPtrExpr::NodeId () ||
 
376
          i->_tree->NodeName () == CT_MembRefExpr::NodeId ()) {
 
377
        CTree *op = i->_tree->Son (1);
 
378
        Token *tok_before = op->token ();
 
379
        const WeavePos &before = _code_weaver.weave_pos (tok_before, WeavePos::WP_BEFORE);
 
380
        _code_weaver.paste (before, string ("/*** op ") +
 
381
          string (i->_info->QualName ()) + string (" ***/\n"));      
 
382
      }
 
383
    }
 
384
  }
 
385
  
 
386
  // mark all classes that contain dynamically introduced attributes
 
387
  JoinPointModel::Selection classes;
 
388
  jpm.select ((JoinPointLoc::join_point_type)(JoinPointLoc::Class|
 
389
    JoinPointLoc::Aspect), classes);
 
390
  for (JoinPointModel::Selection::iterator i = classes.begin ();
 
391
    i != classes.end (); ++i) {
 
392
    JPL_Class *cls = (JPL_Class*)*i;
 
393
    if (!cls->intro_target ())
 
394
      continue;
 
395
    bool mark_class = false;
 
396
    const TI_Class *ti = TI_Class::of (*cls);
 
397
    CClassInfo *ci = ti->class_info ();
 
398
    for (unsigned i = 0; i < ci->Attributes (); i++) {
 
399
      CAttributeInfo *attr = ci->Attribute (i);
 
400
      if (attr->isStatic () || attr->isAnonymous ())
 
401
        continue;
 
402
      Unit *unit = (Unit*)attr->Tree ()->token ()->belonging_to ();
 
403
      IntroductionUnit *iunit = IntroductionUnit::cast (unit);
 
404
      if (iunit) {
 
405
        mark_class = true;
 
406
        JPL_Name *jpl_aspect = iunit->intro ()->parent ();
 
407
        Token *tok_before = attr->Tree ()->ObjDecl ()->token ();
 
408
        const WeavePos &before = _code_weaver.weave_pos (tok_before, WeavePos::WP_BEFORE);
 
409
        _code_weaver.paste (before, string ("/*** +intro ") +
 
410
          string (jpl_aspect->signature ()) + string (" ***/\n"));      
 
411
  
 
412
        Token *tok_after = attr->Tree ()->ObjDecl ()->end_token ();
 
413
        const WeavePos &after = _code_weaver.weave_pos (tok_after, WeavePos::WP_AFTER);
 
414
        _code_weaver.paste (after, string ("/*** -intro ") +
 
415
          string (jpl_aspect->signature ()) + string (" ***/\n"));      
 
416
      }
 
417
    }
 
418
    if (mark_class) {
 
419
      Token *tok_before = ((CT_ClassDef*)ci->Tree ())->ObjDecl ()->token ();
 
420
      const WeavePos &before = _code_weaver.weave_pos (tok_before, WeavePos::WP_BEFORE);
 
421
      _code_weaver.paste (before, string ("/*** +class ") +
 
422
        string (cls->signature ()) + string (" ***/\n"));      
 
423
 
 
424
      Token *tok_after = ((CT_ClassDef*)ci->Tree ())->Members ()->end_token ();
 
425
      const WeavePos &after = _code_weaver.weave_pos (tok_after, WeavePos::WP_BEFORE);
 
426
      _code_weaver.paste (after, string ("/*** -class ") +
 
427
        string (cls->signature ()) + string (" ***/\n"));      
 
428
    }
 
429
  }
 
430
}
 
431
 
 
432
 
 
433
void Transformer::update_intros_in_repo (ModelBuilder &jpm1) {
 
434
  ModelBuilder::Selection intros;
 
435
  jpm1.select (JoinPointLoc::Introduction, intros);
 
436
  for (JoinPointModel::Selection::iterator i = intros.begin ();
 
437
       i != intros.end (); ++i) {
 
438
    JPL_Introduction &intro = *(JPL_Introduction*)*i;
 
439
    _repo.consider (intro);
 
440
  }
 
441
  ModelBuilder::Selection classes;
 
442
  jpm1.select ((JoinPointLoc::join_point_type)(JoinPointLoc::Class|
 
443
    JoinPointLoc::Aspect), classes);
 
444
  for (JoinPointModel::Selection::iterator i = classes.begin ();
 
445
       i != classes.end (); ++i) {
 
446
    JPL_Class &cls = *(JPL_Class*)*i;
 
447
    // get the weaving plan of this intro
 
448
    JPP_Class *plan = (JPP_Class*)cls.plan ();
 
449
    // collect the intros into this class
 
450
    if (plan) {
 
451
      set<JPL_Introduction*> intros;
 
452
      for (int b = 0; b < plan->baseIntros (); b++)
 
453
        intros.insert (plan->baseIntro (b));
 
454
      for (int o = 0; o < plan->otherIntros (); o++)
 
455
        intros.insert (plan->otherIntro (o));
 
456
      // now update the repository with the intro information
 
457
      for (set<JPL_Introduction*>::iterator intro_iter = intros.begin ();
 
458
           intro_iter != intros.end (); ++intro_iter) {
 
459
        _repo.update (**intro_iter, cls);
 
460
      }
 
461
    }
 
462
  }
 
463
}
 
464
 
 
465
void Transformer::aspect_priviledges (ModelBuilder &jpm) {
 
466
  // TODO: access to template classes
 
467
 
 
468
  // get all aspects from the join point model
 
469
  JoinPointModel::Selection all_aspects;
 
470
  jpm.select (JoinPointLoc::Aspect, all_aspects);
 
471
 
 
472
  // remember that these aspects should become friend of all classes
199
473
  list<CClassInfo*> friends;
200
 
  for (int a = 0; a < db.AspectInfos (); a++) {
201
 
    CClassInfo *aspect_cls = db.AspectInfo (a)->ClassInfo ();
202
 
    if (!aspect_cls->Tree () ||
203
 
        !aspect_cls->ClassDB()->Project ()->
204
 
        isBelow (aspect_cls->SourceInfo ()->SrcUnit ()))
205
 
      continue;
206
 
    friends.push_back (aspect_cls);
 
474
  for (JoinPointModel::Selection::iterator iter = all_aspects.begin ();
 
475
       iter != all_aspects.end (); ++iter) {
 
476
    JPL_Aspect &jpl = (JPL_Aspect&)**iter;
 
477
    friends.push_back (((TI_Aspect*)jpl.transform_info ())->ClassInfo());
207
478
  }
 
479
  
208
480
  if (!friends.empty ()) {
209
 
    for (unsigned c = 0; c < db.ClassInfos (); c++) {
210
 
      CClassInfo *cls = db.ClassInfo (c);
211
 
      if (!cls->Tree () ||
212
 
        !cls->ClassDB()->Project ()->isBelow (cls->SourceInfo ()->SrcUnit ()))
 
481
    // get all classes and aspects from the join point model
 
482
    JoinPointModel::Selection all_classes;
 
483
    jpm.select ((JoinPointLoc::join_point_type)
 
484
      (JoinPointLoc::Aspect|JoinPointLoc::Class), all_classes);
 
485
  
 
486
    // perform the transformation
 
487
    for (JoinPointModel::Selection::iterator iter = all_classes.begin ();
 
488
         iter != all_classes.end (); ++iter) {
 
489
      JPL_Class &jpl = (JPL_Class&)**iter;
 
490
      CClassInfo *cls = ((TI_Class*)jpl.transform_info ())->class_info();
 
491
 
 
492
      // TODO: also ignore classes that do no belong to the project
 
493
      if (!cls->isDefined ())
213
494
        continue;
214
 
        
 
495
 
215
496
      // Don't add friend declarations in the AC namespace definitions
216
497
      CScopeInfo *scope = cls->Scope ();
217
498
      while (!scope->GlobalScope ()) {
248
529
 
249
530
 
250
531
void Transformer::introductions (CTranslationUnit &tunit,
251
 
                                 PointCutContext &context, Plan &plan) {
252
 
  CClassDatabase &db = tunit.db ();
253
 
 
254
 
  for (int a = 0; a < db.AspectInfos (); a++) {
255
 
    ACAspectInfo *acai = db.AspectInfo (a);
256
 
 
257
 
    if (acai->is_abstract ())
258
 
      continue;
259
 
    context.aspect_info (acai);
260
 
 
261
 
    _vm << "intros for " << acai->name () << endvm;
262
 
    // create a pointcut evaluator
263
 
    PointCutEvaluator eva (_err, context);
264
 
 
265
 
    // now handle the introductions of this aspect
266
 
    AspectInfo *ai = plan.addAspect (acai);
267
 
    
268
 
    // add all the introductions (including inherited ones) to the aspect
269
 
    collect_intros (plan, db, ai, acai);
270
 
 
271
 
    _vm++;
272
 
    int i = 0;
273
 
    for (list<IntroductionInfo *>::iterator iter = ai->intro_infos ().begin ();
274
 
      iter != ai->intro_infos ().end (); ++iter, ++i) {
275
 
      IntroductionInfo *ii = (*iter);
276
 
      ACIntroductionInfo *acii = ii->ac_info ();
277
 
      CT_AdviceDecl *ad = acii->def_node ();
278
 
 
279
 
      ii->print (_vm);
280
 
      _vm << endvm;
281
 
 
282
 
      // check whether the slice is defined
283
 
      if (ii->type () == IntroductionInfo::INTRO_SLICE_DECL ||
284
 
          ii->type () == IntroductionInfo::INTRO_SLICE_REF) {
285
 
        ACSliceInfo *acsi = db.SliceInfo (ii->object(0));
286
 
        assert (acsi);
287
 
        if (!acsi->definition ()) {
288
 
          _err << sev_error << ad->token ()->location ()
289
 
               << "undefined slice '" << ii->object (0)->QualName ()
290
 
               << "' used in advice" << endMessage;
291
 
          continue;
292
 
        }
293
 
        if (acsi->type () == ACSliceInfo::SL_UNION) {
294
 
          _err << sev_error << ad->token ()->location ()
295
 
               << "union slices are not supported by ac++, yet" << endMessage;
296
 
          continue;
297
 
        }
298
 
      }
299
 
      else {
300
 
        if (_conf.warn_deprecated ())
301
 
          _err << sev_warning << ad->token ()->location ()
302
 
               << "deprecated introduction syntax, "
303
 
               << "use slice instead." << endMessage;
304
 
      }
305
 
      
306
 
      // evaluate the pointcut for this introduction
307
 
      PointCut target_scopes;
308
 
      Binding binding;
309
 
      eva.work (target_scopes, binding, ad->Pointcut (),
310
 
        (JoinPointLoc::join_point_type)
311
 
        (JoinPointLoc::Class | JoinPointLoc::Aspect));
312
 
      assert (!binding._used);
313
 
      if (_err.severity () >= sev_error)
314
 
        continue;
315
 
 
316
 
      // do the introduction into all classes refered by the pointcut
317
 
      _vm++;
318
 
      for (PointCut::iterator iter = target_scopes.begin ();
319
 
           iter != target_scopes.end (); ++iter) {
320
 
        const JoinPoint& jp = *iter;
321
 
 
322
 
        assert (jp.type () == JoinPointLoc::Class ||
323
 
                jp.type () == JoinPointLoc::Aspect);
324
 
 
325
 
        CClassInfo *cls = ((JPL_Class*)jp.location ())->class_info ();
326
 
 
327
 
        if (!cls->ClassDB()->Project ()->
328
 
            isBelow (cls->SourceInfo ()->SrcUnit ()))
329
 
          continue;
330
 
 
331
 
        _vm << "into " << cls->Name () << endvm;
332
 
 
333
 
        // consider the introduction in the big plan
334
 
        plan.consider (jp.location (), ii);
335
 
 
336
 
        // don't forget to include the aspect header, where some code is
337
 
        // introduced
338
 
        _code_weaver.add_intro_include ((JPL_Class*)jp.location (), ii);
339
 
      }  
340
 
      _vm--;
341
 
 
342
 
      // update the project repository
343
 
      _repo.update (*ii, target_scopes);
344
 
    }
345
 
    _vm--;
346
 
  }
347
 
 
348
 
  if (_err.severity () >= sev_error)
349
 
    return;
350
 
 
351
 
  _vm << "Aspect ordering ..." << endvm;
352
 
  orderings(tunit, plan, context, false);
353
 
 
354
 
  // now do the final checks on the accumulated plan
355
 
  _vm << "Final checks before weaving introductions" << endvm;
356
 
  plan.check ();
357
 
 
358
 
  // Don't weave if there were errors in the planning phase
359
 
  if (_err.severity () >= sev_error)
360
 
    return;
361
 
 
362
 
  _vm << "Class Join Points" << endvm;
363
 
  _vm++;
364
 
  for (int i = 0; i < plan.class_jp_plans (); i++) {
365
 
    JPP_Class &jp_plan = plan.class_jp_plan (i);
366
 
    JPL_Class &jp_loc = plan.class_jp_loc (i);
367
 
    
368
 
    _vm << jp_loc.signature () << endvm;
369
 
 
370
 
    // introduce base classes
371
 
    _code_weaver.baseclass (jp_loc, jp_plan);
372
 
    
373
 
    // handle other intros
374
 
    for (int i = 0; i < jp_plan.otherIntros (); i++) {
375
 
      IntroductionInfo *ii = jp_plan.otherIntro (i);
376
 
      
377
 
      if (ii->type () == IntroductionInfo::INTRO_SLICE_DECL ||
378
 
          ii->type () == IntroductionInfo::INTRO_SLICE_REF) {
379
 
        ACSliceInfo *acsi = db.SliceInfo (ii->object(0))->definition ();
380
 
        for (int m = 0; m < acsi->members (); m++)
381
 
          _code_weaver.introduce (&jp_loc, acsi->member (m),
382
 
            CProtection::PROT_NONE, _primary_end);
383
 
      }
384
 
      else {
385
 
        _code_weaver.introduce (&jp_loc, ii->tree ()->Decl (), ii->prot (),
386
 
          _primary_end);
387
 
      }
388
 
    }
389
 
  }
390
 
  _vm--;
 
532
  ModelBuilder &jpm) {
 
533
 
 
534
  // remove the introductions from the code
 
535
  ModelBuilder::Selection intros;
 
536
  jpm.select (JoinPointLoc::Introduction, intros);
 
537
  for (JoinPointModel::Selection::iterator i = intros.begin ();
 
538
       i != intros.end (); ++i) {
 
539
    JPL_Introduction &intro = *(JPL_Introduction*)*i;
 
540
    _code_weaver.kill (TI_Introduction::of (intro)->tree ());
 
541
  }
391
542
 
392
543
  // now delete all slice definitions
 
544
  CClassDatabase &db = tunit.db ();
393
545
  for (int s = 0; s < db.SliceInfos (); s++) {
394
546
    ACSliceInfo *acsi = db.SliceInfo (s);
395
547
    // first all members
401
553
    if (!acsi->in_advice ())
402
554
      _code_weaver.kill (acsi->def_node ());
403
555
  }
404
 
  
405
 
  // finally remove the introductions from the code
406
 
  for (int i = 0; i < plan.intros (); i++)
407
 
    _code_weaver.kill (plan.intro (i)->tree ());
408
 
    
409
 
  return;
410
556
}
411
557
 
412
558
void Transformer::orderings (CTranslationUnit &tunit, Plan& plan,
413
 
                             PointCutContext& context, bool purge) {
414
 
 
415
 
  CClassDatabase &db = tunit.db ();
416
 
 
417
 
  for (int a = 0; a < db.AspectInfos (); a++) {
418
 
 
419
 
    ACAspectInfo *acai = db.AspectInfo (a);
420
 
    if (acai->is_abstract ())
421
 
      continue;
422
 
    context.aspect_info (acai);
423
 
    
424
 
    // create a pointcut evaluator
425
 
    PointCutEvaluator eva (_err, context);
426
 
 
427
 
    // collect all order statements of this aspect and its parents
428
 
    Array<CT_AdviceDecl*> order_nodes;
429
 
    collect_ordering (db, acai, order_nodes);
430
 
 
431
 
    AspectInfo *ai = plan.getAspect (acai);
432
 
    
433
 
    _vm++;
434
 
    for (int i = 0; i < (int)order_nodes.length (); i++) {
435
 
      CT_AdviceDecl *ad = order_nodes[i];
436
 
      CT_OrderList *lst = ((CT_OrderDecl*)ad->Decl ())->OrderList ();
437
 
 
438
 
      _vm << acai->name() << ":";
439
 
 
440
 
      OrderInfo *order_info = plan.addOrder(ai, ad);
441
 
      
442
 
      // resolve all pointcut expressions first
443
 
      Array<ACAspectInfo*> *ais = new Array<ACAspectInfo*>[lst->Entries ()];
444
 
 
445
 
      for (int n = 0; n < lst->Entries (); n++) {
446
 
 
447
 
        if (n != 0)
448
 
          _vm << " ->";
449
 
 
450
 
        // evaluate the current pointcut
451
 
        PointCut pct;
452
 
        Binding binding; // must be unused here
453
 
        eva.work (pct, binding, lst->Entry (n), JoinPointLoc::Aspect);
454
 
        assert (!binding._used);
455
 
 
456
 
        // check all join points in this pointcut
457
 
        for (PointCut::iterator iter = pct.begin ();
458
 
             iter != pct.end (); ++iter) {
459
 
          const JoinPoint &jp = *iter;
460
 
 
461
 
          // get the AspectInfo object of this aspect
462
 
          ACAspectInfo* ai = ((JPL_Aspect*)jp.location ())->aspect_info ();
463
 
 
464
 
          // remember this aspect
465
 
          ais[n].append (ai);
466
 
 
467
 
          _vm << " " << ai->name ();
468
 
        }
469
 
      }
470
 
      _vm << endvm;
471
 
 
472
 
      // now collect pairs of order requirements
473
 
      Array<ACAspectInfo*> oai_l; // aspect with lower precedence
474
 
      Array<ACAspectInfo*> oai_h; // aspect with higher precedence
475
 
 
476
 
      for (int n = 1; n < lst->Entries (); n++)
477
 
        for (int h = 0; h < ais[n - 1].length (); h++)
478
 
          for (int l = 0; l < ais[n].length (); l++) {
479
 
            oai_h.append (ais[n - 1].lookup (h));
480
 
            oai_l.append (ais[n].lookup (l));
481
 
          }
482
 
 
483
 
      delete[] ais;
484
 
 
485
 
      // evaluate the pointcut for this ordering
486
 
      PointCut target;
487
 
      Binding binding;
488
 
      eva.work (target, binding, ad->Pointcut (), JoinPointLoc::Any);
489
 
      assert (!binding._used);
490
 
 
491
 
      // remember the ordering in all JPP refered by the pointcut
492
 
      for (PointCut::iterator iter = target.begin ();
493
 
           iter != target.end (); ++iter) {
494
 
        const JoinPoint &jp = *iter;
495
 
        // remember the ordering in the big plan
496
 
        for (int i = 0; i < oai_l.length (); i++)
497
 
          plan.consider (jp.location (), *oai_h[i], *oai_l[i]);
498
 
      }
499
 
 
500
 
      if (purge) _code_weaver.kill (ad);
501
 
      
502
 
      // update the project repository
503
 
      _repo.update (*order_info);
 
559
                             ModelBuilder &jpm, bool purge) {
 
560
 
 
561
  // let the plan object calculate the right order
 
562
  plan.order ();
 
563
 
 
564
  // remove the introductions from the code
 
565
  if (purge) {
 
566
    // Iterate through order advice declarations
 
567
    ModelBuilder::Selection orders;
 
568
    jpm.select (JoinPointLoc::Order, orders);
 
569
    for (JoinPointModel::Selection::iterator i = orders.begin ();
 
570
       i != orders.end (); ++i) {
 
571
      JPL_Order &order = *(JPL_Order*)*i;
 
572
      TI_Order  &ti   = *TI_Order::of (order);
 
573
      _code_weaver.kill (ti.tree ());
504
574
    }
505
 
    _vm--;
506
575
  }
507
576
}
508
577
 
553
622
  }
554
623
}
555
624
 
556
 
void Transformer::collect_intros (Plan &plan, CClassDatabase &db,
557
 
  AspectInfo *ai, ACAspectInfo *acai) {
558
 
  for (int i = 0; i < acai->IntroNodes (); i++)
559
 
    plan.addIntroduction (ai, acai->IntroNode (i));
560
 
 
561
 
  for (unsigned b = 0; b < acai->ClassInfo ()->BaseClasses (); b++) {
562
 
    CClassInfo *base = acai->ClassInfo ()->BaseClass (b)->Class ();
563
 
    ACAspectInfo *base_aspect = db.AspectInfo (base);
564
 
    if (base_aspect)
565
 
      collect_intros (plan, db, ai, base_aspect);
566
 
  }
567
 
}
568
 
 
569
 
void Transformer::collect_advice (CClassDatabase &db, ACAspectInfo *ai,
570
 
                                  Array<CT_AdviceDecl*> &advice_nodes) {
571
 
  for (int i = 0; i < ai->AdviceNodes (); i++)
572
 
    advice_nodes.append (ai->AdviceNode (i));
573
 
 
574
 
  for (unsigned b = 0; b < ai->ClassInfo ()->BaseClasses (); b++) {
575
 
    CClassInfo *base = ai->ClassInfo ()->BaseClass (b)->Class ();
576
 
    ACAspectInfo *base_aspect = db.AspectInfo (base);
577
 
    if (base_aspect)
578
 
      collect_advice (db, base_aspect, advice_nodes);
579
 
  }
580
 
}
581
 
 
582
 
void Transformer::collect_ordering (CClassDatabase &db, ACAspectInfo *ai,
583
 
                                    Array<CT_AdviceDecl*> &order_nodes) {
584
 
  for (int i = 0; i < ai->OrderNodes (); i++)
585
 
    order_nodes.append (ai->OrderNode (i));
586
 
 
587
 
  for (unsigned b = 0; b < ai->ClassInfo ()->BaseClasses (); b++) {
588
 
    CClassInfo *base = ai->ClassInfo ()->BaseClass (b)->Class ();
589
 
    ACAspectInfo *base_aspect = db.AspectInfo (base);
590
 
    if (base_aspect)
591
 
      collect_ordering (db, base_aspect, order_nodes);
592
 
  }
593
 
}
594
 
 
595
625
void Transformer::join_points (CTranslationUnit &tunit,
596
 
                               PointCutContext &context) {
597
 
  CClassDatabase &db = tunit.db ();
598
 
  Plan plan (_err);
599
 
 
 
626
                               ModelBuilder &jpm, Plan &plan) {
600
627
  _vm++;
601
628
 
602
629
  _vm << "Advicecode manipulation" << endvm;
603
630
  // Iterate through advice
604
 
  for (int a = 0; a < db.AspectInfos (); a++) {
605
 
    ACAspectInfo *acai = db.AspectInfo (a);
606
 
    for (int i = 0; i < acai->AdviceNodes (); i++) {
607
 
      CT_AdviceDecl *ad = acai->AdviceNode (i);
608
 
      // register advice code in the big plan
609
 
      AdviceCode *code = plan.addAdviceCode (ad);
610
 
      // setup ThisJoinPoint object of this advice code
611
 
      code->this_join_point ().setup (code->function ());
612
 
      _code_weaver.provide_tjp (code->function (), code->this_join_point ());
613
 
    }
 
631
  ModelBuilder::Selection advice_codes;
 
632
  jpm.select (JoinPointLoc::AdviceCode, advice_codes);
 
633
  for (JoinPointModel::Selection::iterator i = advice_codes.begin ();
 
634
       i != advice_codes.end (); ++i) {
 
635
    JPL_AdviceCode &code = *(JPL_AdviceCode*)*i;
 
636
    TI_AdviceCode  &ti   = *TI_AdviceCode::of (code);
 
637
    // setup ThisJoinPoint object of this advice code
 
638
    ti.this_join_point ().setup (ti.function ());
 
639
    _code_weaver.provide_tjp (ti.function (), ti.this_join_point ());
614
640
  }
615
641
 
616
642
  _vm << "Collecting Advice" << endvm;
618
644
  _vm++;
619
645
 
620
646
  // Create a pointcut evaluator
 
647
  PointCutContext context (jpm);
621
648
  PointCutEvaluator eva (_err, context);
622
649
 
623
 
  for (int a = 0; a < db.AspectInfos (); a++) {
624
 
    ACAspectInfo *acai = db.AspectInfo (a);
625
 
 
626
 
    // Don't weave advice of abstract aspects
627
 
    if (acai->is_abstract ())
628
 
      continue;
629
 
 
630
 
    context.aspect_info (acai);
 
650
  Plan::AspectContainer &aspects = plan.aspect_infos ();
 
651
  for (Plan::AspectContainer::iterator i = aspects.begin ();
 
652
    i != aspects.end (); ++i) {
 
653
    AspectInfo &aspect_info = (AspectInfo&)*i;
 
654
    JPL_Aspect &jpl_aspect = aspect_info.loc ();
 
655
 
 
656
    context.concrete_aspect (jpl_aspect);
631
657
    int index = 0; // CFlow index (each CFlow has a unique index per aspect)
632
658
 
633
 
    AspectInfo *ai = plan.addAspect (acai);
634
 
 
635
659
    // setup thisJoinPoint for aspectOf function, if there is one
636
 
    if (ai->aspectof()) {
 
660
    CFunctionInfo *aspect_of_func = TI_Aspect::of (jpl_aspect)->aspectof();
 
661
    if (aspect_of_func) {
637
662
      _vm << "Setting up thisJoinPoint for aspectof" << endvm;
638
 
        ai->aspectof_this_join_point ().setup (ai->aspectof ());
 
663
        aspect_info.aspectof_this_join_point ().setup (aspect_of_func);
639
664
      _vm << "Supplying aspectof() with JoinPoint and tjp if needed" << endvm;
640
 
      _code_weaver.provide_tjp (ai->aspectof (), ai->aspectof_this_join_point ());
 
665
      _code_weaver.provide_tjp (aspect_of_func,
 
666
        aspect_info.aspectof_this_join_point ());
641
667
    }
642
668
 
643
 
    // traverse inheritance tree and collect advice declarations
644
 
    Array<CT_AdviceDecl*> advice_nodes;
645
 
    collect_advice (db, acai, advice_nodes);
 
669
    // handle the advice for the current aspect
 
670
    list<AdviceInfo*> advices = aspect_info.advice_infos ();
646
671
 
647
672
    // handle advice
648
 
    for (int i = 0; i < (int)advice_nodes.length (); i++) {
649
 
        CT_AdviceDecl *ad = advice_nodes[i];
650
 
      AdviceInfo *advice_info = plan.addAdvice (ai, ad);
651
 
 
652
 
        CFunctionInfo *adfunc = advice_info->code ().function ();
653
 
 
654
 
        _vm << acai->name () << ": "  << adfunc->Name () << endvm;
655
 
        _vm++;
 
673
    for (list<AdviceInfo*>::const_iterator i = advices.begin ();
 
674
      i != advices.end (); ++i) {
 
675
      AdviceInfo *advice_info = *i;
 
676
      JPL_AdviceCode *code = &advice_info->code ();
 
677
      CFunctionInfo *adfunc = TI_AdviceCode::of (*code)->function ();
 
678
 
 
679
      _vm << jpl_aspect.signature () << ": "  << adfunc->Name () << endvm;
 
680
      _vm++;
656
681
 
657
682
        // evaluate the pointcut, even inherited
658
683
        _vm << "Evaluate Pointcut" << endvm;
659
684
        PointCut &pc = advice_info->pointcut ();
660
 
      Binding &binding = advice_info->code ().binding ();
 
685
      Binding &binding = advice_info->binding ();
661
686
        context.func (adfunc);
662
 
        eva.work (pc, binding, ad->Pointcut (), JoinPointLoc::Code);
 
687
        eva.work (pc, binding, code->expr (), JoinPointLoc::Code);
663
688
        if (_err.severity () >= sev_error) {
664
689
            _vm--;
665
690
        continue;
674
699
        plan.consider (jp.location (), jp.condition (), advice_info);
675
700
 
676
701
        // remember units for inclusion of aspect headers
677
 
        // TODO: AR_DEF shall soon be replace by AR_ADVICE!
678
 
        _code_weaver.add_aspect_include (jp.location (), ai, acai,
 
702
        _code_weaver.add_aspect_include (jp.location (), aspect_info,
679
703
                                         AspectRef::AR_ADVICE);
680
704
      }
681
705
 
693
717
          plan.consider (jp.location (), CFlow (advice_info, index));
694
718
          
695
719
          // remember units for inclusion of aspect headers
696
 
          _code_weaver.add_aspect_include (jp.location (), ai, acai,
 
720
          _code_weaver.add_aspect_include (jp.location (), aspect_info,
697
721
                                           AspectRef::AR_DECL);
698
722
          
699
723
        }
700
724
      }
701
725
      
702
726
      // update the project repository
703
 
      _repo.update (*advice_info, pc);
 
727
      if (getenv ("ACNEWREPO") == 0)
 
728
        _repo.update (*advice_info, pc);
704
729
 
705
730
      _vm--;
706
731
    }
 
732
    
 
733
    // add order advices to plan
 
734
    list<JPL_Order*> orders;
 
735
    jpl_aspect.collect_orders (orders);
 
736
    
 
737
    for (list<JPL_Order*>::iterator i = orders.begin ();
 
738
      i != orders.end (); ++i) {
 
739
      OrderInfo *oi = plan.addOrder (jpl_aspect, **i);
 
740
      oi->analyze_exprs (_err, jpm);
 
741
    }
707
742
 
708
 
    _code_weaver.invocation_functions (acai, _primary_start,
709
 
                                       ai->ifct_decls (), ai->ifct_defs ());
 
743
    ACAspectInfo *acai = TI_Aspect::of (jpl_aspect)->aspect_info();
 
744
    _code_weaver.invocation_functions (acai,
 
745
      aspect_info.ifct_decls (_code_weaver.problems ()),
 
746
      aspect_info.ifct_defs (_code_weaver.problems ()));
710
747
  }
711
748
  _vm--;
712
749
 
713
750
  _vm << "Aspect ordering ..." << endvm;
714
 
  orderings(tunit, plan, context, true);
 
751
  orderings(tunit, plan, jpm, true);
715
752
 
716
753
  // now do the final checks on the accumulated plan
717
754
  _vm << "Final checks before weaving code join points" << endvm;
721
758
  if (_err.severity () >= sev_error)
722
759
    return;
723
760
 
 
761
  char *repo_file = getenv ("ACNEWREPO");
 
762
  if (repo_file) {
 
763
#ifdef _MSC_VER
 
764
    if (!_access (repo_file, 04)) {
 
765
#else
 
766
    if (!access (repo_file, R_OK)) {
 
767
#endif // _MSC_VER
 
768
 
 
769
      _vm << "Opening new project repository '" << repo_file << "'" << endvm;
 
770
      int fd = SysCall::open_excl (repo_file, O_RDWR, &_err);
 
771
      JoinPointModel ljpm;
 
772
      JoinPointModel::FileOpResult res = ljpm.load (fd, repo_file);
 
773
      if (res == JoinPointModel::JPM_LOAD_ERR) {
 
774
        _err << sev_error << "project repository '" << repo_file << "' cannot be opened"
 
775
        " or is invalid" << endMessage;
 
776
        return;
 
777
      }
 
778
      if (res == JoinPointModel::JPM_VERSION) {
 
779
        _err << sev_warning << "project file version differs from ac++ version"
 
780
            << endMessage;
 
781
      }
 
782
      ljpm.reconcile (jpm);
 
783
      lseek (fd, 0, SEEK_SET);
 
784
      if (ftruncate (fd, 0) != 0)
 
785
        perror ("truncate");
 
786
      ljpm.save (fd, repo_file);
 
787
      SysCall::close_excl (fd, &_err);
 
788
    }
 
789
    else {
 
790
      int fd = SysCall::create_excl (repo_file, 0600, &_err);
 
791
      jpm.save (fd, repo_file);
 
792
      SysCall::close_excl  (fd, &_err);
 
793
    }
 
794
  }
 
795
 
724
796
  _vm << "Type Check Functions" << endvm;
725
797
  _vm++;
726
798
  const TypeCheckSet &checks_false = plan.type_checks_false ();
797
869
   _vm--;
798
870
 
799
871
   _vm << "Aspect Includes ..." << endvm;
800
 
   _code_weaver.aspect_includes (_project, _primary_start);
 
872
   _code_weaver.aspect_includes (_project);
801
873
 }
802
874