~siretart/aspectc++/debian

« back to all changes in this revision

Viewing changes to AspectC++/Transformer.cc

  • Committer: Reinhard Tartler
  • Date: 2013-10-13 18:20:07 UTC
  • mto: This revision was merged to the branch mainline in revision 101.
  • Revision ID: siretart@tauware.de-20131013182007-qc3ibv60inzzk8l4
Tags: upstream-1.2
ImportĀ upstreamĀ versionĀ 1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
// AspectC++ includes
20
20
#include "Transformer.h"
21
 
#include "JPAdvice.h"
22
 
#include "PointCutEvaluator.h"
23
21
#include "PointCut.h"
24
22
#include "PointCutContext.h"
25
23
#include "OrderInfo.h"
26
24
#include "AdviceInfo.h"
27
25
#include "AspectInfo.h"
28
26
#include "IntroductionInfo.h"
29
 
#include "JoinPointPlan.h"
30
27
#include "Plan.h"
31
28
#include "Repository.h"
32
29
#include "PointCutContext.h"
39
36
#include "ModelBuilder.h"
40
37
#include "IntroductionUnit.h"
41
38
#include "version.h"
42
 
#ifdef ACMODEL
43
 
#include "XmlModelWriter.h"
44
 
#include "XmlModelReader.h"
45
 
#endif
 
39
#include "ACModel/XmlModelWriter.h"
 
40
#include "ACModel/XmlModelReader.h"
 
41
#include "Phase1.h"
46
42
 
47
43
// PUMA includes
48
44
#include "Puma/CProject.h"
53
49
#include "Puma/CArgumentInfo.h"
54
50
#include "Puma/CTranslationUnit.h"
55
51
#include "Puma/CSemDatabase.h"
56
 
#include "Puma/ACAspectInfo.h"
57
 
#include "Puma/ACAdviceInfo.h"
58
 
#include "Puma/ACIntroductionInfo.h"
59
 
#include "Puma/ACPointcutInfo.h"
60
 
#include "Puma/ACTree.h"
61
52
#include "Puma/CPrintVisitor.h"
62
53
#include "Puma/SysCall.h"
63
54
#ifdef PROFILING
78
69
 
79
70
void Transformer::work (Unit *unit, Token *primary_start, Token *primary_end) {
80
71
 
81
 
  // set the start and end token of the unit
82
 
  _code_weaver.init (primary_start, primary_end);
83
 
  
84
72
  // determine back-end compiler problems and setup code weaver
85
73
  BackEndProblems back_end_problems;
86
74
  back_end_problems._local_class       = _conf.problem_local_class ();
91
79
  back_end_problems._warn_deprecated   = _conf.warn_deprecated();
92
80
  _code_weaver.problems (back_end_problems);
93
81
  
 
82
  // set the start and end token of the unit
 
83
  _code_weaver.init (primary_start, primary_end, back_end_problems._warn_macro);
 
84
 
94
85
  // perform the transformation
95
86
  CTranslationUnit *tunit1 = 0;
96
 
  ModelBuilder jpm (_vm, _err, _conf);
 
87
  ModelBuilder jpm (_vm, _err, _conf, _project);
 
88
  jpm.set_version(ac_version ());
 
89
  IncludeGraph ig (_project);
97
90
  
98
 
  bool ok = (phase1 (unit, tunit1, jpm) &&
99
 
             phase2 (unit, tunit1, jpm));
 
91
  bool ok = (phase1 (unit, tunit1, jpm, ig) &&
 
92
             phase2 (unit, tunit1, jpm, ig));
100
93
  if (tunit1)
101
94
    delete tunit1;
102
95
  if (!ok)
104
97
}
105
98
 
106
99
bool Transformer::phase1 (Unit *unit, CTranslationUnit *&tunit,
107
 
                          ModelBuilder &jpm) {
 
100
                          ModelBuilder &jpm, IncludeGraph &ig) {
108
101
 
109
102
#ifdef PROFILING
110
103
  static Profiler::Data data (__PRETTY_FUNCTION__, NULL);
113
106
 
114
107
  _vm << "Inserting namespace AC" << endvm;
115
108
  // in front of start!
116
 
  _code_weaver.insert_namespace_ac_before ((Token*)unit->first ());
 
109
  _code_weaver.insert_namespace_ac ();
117
110
 
118
111
  if (!_conf.iterate () && !_conf.ifiles () && _conf.file_in ()) {
119
112
    // STU mode and not generating transformed headers!
138
131
    }
139
132
    if (forced_includes != "") {
140
133
      _vm << "Inserting forced includes" << endvm;
141
 
      _code_weaver.paste (_code_weaver.weave_pos ((Token*)unit->first (), WeavePos::WP_BEFORE),
142
 
        forced_includes);
 
134
      _code_weaver.insert (_code_weaver.header_pos (), forced_includes);
143
135
      for (list<const ConfOption*>::iterator i = forced_include_opts.begin ();
144
136
        i != forced_include_opts.end (); ++i)
145
137
        _conf.project().config().Remove(*i);
147
139
  }
148
140
  _code_weaver.commit ();
149
141
  
 
142
  // prepare the project model
 
143
  jpm.setup_phase1((FileUnit*)unit, _code_weaver.primary_len());
 
144
 
 
145
  // fill the model while parsing the AOP elements of the language in phase 1
150
146
  _vm << "Parsing ..." << endvm;
151
 
  // parse the translation unit, but ignore function bodies
152
 
  unsigned options = _parser.Options ();
153
 
  _parser.Options (options | CCParser::SKIP_FCT_BODY);
154
 
  tunit = _parser.parse (*unit, _project);
155
 
  _parser.Options (options);
156
 
  // do semantic analysis of expressions
157
 
  _sem_visitor.run (tunit->tree ());
158
 
  
159
 
  if (_err.severity () >= sev_error)
160
 
    return false;
161
 
 
162
 
//  tunit->unit ()->print(cout);
163
 
//  CPrintVisitor printer;
164
 
//  printer.print (tunit->tree (), cout);
165
 
 
166
 
  //    Some debugging code:
167
 
  //    tunit->unit ()->print(cout);
168
 
  //    CPrintVisitor printer;
169
 
  //    printer.print (tunit->tree (), cout);
170
 
  //    tunit->db ().Dump (cout, 2);
171
 
  
172
 
  // create the phase 1 join point model
173
 
  _vm << "Setting up join point model 1 ..." << endvm;
174
 
  _vm++;
175
 
  int tunit_len = _code_weaver.primary_end ()->location().line() -
176
 
      _code_weaver.primary_start()->location().line() + 1;
177
 
  jpm.setup_phase1 (*tunit, tunit_len);
178
 
  _vm--;
179
 
  
 
147
  Phase1 phase1 (jpm, *unit, _project, _code_weaver);
 
148
  phase1.run (ig);
 
149
//  cout << "Project Model after Phase1" << endl;
 
150
//  jpm.dump();
 
151
 
180
152
  // set up the project repository
181
153
  _repo.setup (jpm.tunit_file());
182
154
 
183
 
  _vm << "Setting Aspect Access Privileges ..." << endvm;
184
 
  aspect_privileges (jpm);
185
 
  
186
 
  _vm << "Weaving Introductions ..." << endvm;
187
 
  introductions (*tunit, jpm);
188
 
      
189
 
  _vm << "Weaving Advice Declarations ..." << endvm;
190
 
  advice (*tunit);
191
 
  
192
 
  _vm << "Weaving Singleton Aspects ..." << endvm;
193
 
  singleton_aspects (*tunit);
194
 
 
195
 
//  _vm << "Slice/Intro Includes ..." << endvm;
196
 
//  _code_weaver.slice_includes (_project, _primary_start);
 
155
  // generate a string with aspect forward declarations
 
156
  _vm << "Weaving Aspects Forward Declarations ..." << endvm;
 
157
  determine_aspect_fwd_decls (jpm);
 
158
  _code_weaver.insert (_code_weaver.weave_pos ((Token*)unit->first (), WeavePos::WP_BEFORE),
 
159
    _aspect_fwd_decls);
197
160
 
198
161
  _vm << "Committing" << endvm;
199
162
  _code_weaver.commit ();
200
163
 
 
164
 
 
165
  // Some debugging code:
 
166
//  unit->print(cout);
 
167
 
201
168
//    _vm << "Stage1 save!" << endvm;
202
169
//    _project.save();
203
170
//    _vm << " done." << endvm;
213
180
}
214
181
 
215
182
bool Transformer::phase2 (Unit *unit, CTranslationUnit *tunit1,
216
 
                          ModelBuilder &jpm) {
 
183
                          ModelBuilder &jpm, IncludeGraph &ig) {
217
184
 
218
185
#ifdef PROFILING
219
186
  static Profiler::Data data (__PRETTY_FUNCTION__, NULL);
220
187
  Profiler::ClockTicks start = Profiler::rdtsc ();
221
188
#endif
222
189
 
223
 
  IncludeGraph ig (_project);
224
 
  ig.init (*tunit1);
225
 
//  ig.dump ();
226
 
  
 
190
  Plan plan (_err, jpm);
 
191
 
227
192
  _vm << "Preparing introductions ..." << endvm;
228
 
  Plan plan (_err, jpm);
229
193
  PointCutContext context (jpm);
230
 
  PointCutEvaluator eval (_err, context);
231
 
 
232
 
  // get all aspects from the plan (in some order)
233
 
  const Plan::AspectContainer &aspects = plan.aspect_infos ();
234
 
  for (Plan::AspectContainer::const_iterator i = aspects.begin ();
235
 
    i != aspects.end (); ++i) {
236
 
    
237
 
#ifdef ACMODEL
238
 
    ACM_Aspect &jpl_aspect = i->loc ();
239
 
    context.concrete_aspect (jpl_aspect);
240
 
 
241
 
    // add introductions to plan
242
 
    list<ACM_Introduction*> intros;
243
 
    collect_intros (jpl_aspect, intros);
244
 
    
245
 
    for (list<ACM_Introduction*>::iterator i = intros.begin ();
246
 
      i != intros.end (); ++i) {
247
 
      IntroductionInfo *ii = plan.addIntroduction (jpl_aspect, **i);
248
 
      ii->pointcut_expr () =
249
 
        eval.create (TI_PointcutExpr::of(*(*i)->get_expr ())->tree(), JPT_Name);
250
 
      if (!(ii->pointcut_expr()->possible_types() & JPT_Class)) {
251
 
        _err  << sev_warning << TI_Introduction::of(ii->intro ())->loc()
252
 
             << "pointcut expression for introduction can't match class"
253
 
             << endMessage;
254
 
      }
255
 
    }
256
 
 
257
 
    // add order advices to plan
258
 
    list<ACM_Order*> orders;
259
 
    collect_orders (jpl_aspect, orders);
260
 
    
261
 
    for (list<ACM_Order*>::iterator i = orders.begin ();
262
 
      i != orders.end (); ++i) {
263
 
      OrderInfo *oi = plan.addOrder (jpl_aspect, **i);
264
 
      oi->analyze_exprs (eval);
265
 
      if (!getenv ("ACNEWREPO")) {
266
 
        _repo.update (*oi);
267
 
      }
268
 
    }
269
 
#else
270
 
    JPL_Aspect &jpl_aspect = i->loc ();
271
 
    context.concrete_aspect (jpl_aspect);
272
 
 
273
 
    // add introductions to plan
274
 
    list<JPL_Introduction*> intros;
275
 
    jpl_aspect.collect_intros (intros);
276
 
    
277
 
    for (list<JPL_Introduction*>::iterator i = intros.begin ();
278
 
      i != intros.end (); ++i) {
279
 
      IntroductionInfo *ii = plan.addIntroduction (jpl_aspect, **i);
280
 
      ii->pointcut_expr() = eval.create ((*i)->expr (), JoinPointLoc::Name);
281
 
      if (!(ii->pointcut_expr()->possible_types() & JoinPointLoc::Class)) {
282
 
        _err  << sev_warning << TI_Introduction::of(ii->intro ())->loc()
283
 
             << "pointcut expression for introduction can't match class"
284
 
             << endMessage;
285
 
      }
286
 
    }
287
 
 
288
 
    // add order advices to plan
289
 
    list<JPL_Order*> orders;
290
 
    jpl_aspect.collect_orders (orders);
291
 
    
292
 
    for (list<JPL_Order*>::iterator i = orders.begin ();
293
 
      i != orders.end (); ++i) {
294
 
      OrderInfo *oi = plan.addOrder (jpl_aspect, **i);
295
 
      oi->analyze_exprs (eval);
296
 
      if (!getenv ("ACNEWREPO")) {
297
 
        _repo.update (*oi);
298
 
      }
299
 
    }
300
 
#endif
 
194
 
 
195
  // perform semantic analysis of all pointcut expressions used for introductions
 
196
  const list<IntroductionInfo*> &intros = plan.introduction_infos ();
 
197
  for (list<IntroductionInfo*>::const_iterator i = intros.begin ();
 
198
       i != intros.end (); ++i) {
 
199
    IntroductionInfo *intro_info = *i;
 
200
    ACM_Introduction &intro = intro_info->intro();
 
201
    context.concrete_aspect(intro_info->aspect());
 
202
    context.pct_func (intro.get_pointcut());
 
203
    intro_info->pointcut_expr()->semantics(_err, context);
 
204
    if (!(intro_info->pointcut_expr()->possible_types() & JPT_Class)) {
 
205
      _err << sev_warning
 
206
           << Location (Filename (filename (intro).c_str ()), line (intro))
 
207
           << "pointcut expression for introduction can't match class"
 
208
           << endMessage;
 
209
    }
 
210
  }
 
211
 
 
212
  // ... and also for the pointcut expressions in order advice
 
213
  const list<OrderInfo*> &orders = plan.order_infos ();
 
214
  for (list<OrderInfo*>::const_iterator i = orders.begin ();
 
215
       i != orders.end (); ++i) {
 
216
    OrderInfo *oi = *i;
 
217
    context.concrete_aspect (oi->aspect());
 
218
    oi->analyze_exprs (_err, context);
 
219
    if (getenv ("ACOLDREPO")) {
 
220
      _repo.update (*oi);
 
221
    }
301
222
  }
302
223
 
303
224
  _vm << "Parsing again ..." << endvm;
330
251
  //    CPrintVisitor printer;
331
252
  //    printer.print (tunit->tree (), cout);
332
253
  
333
 
  _vm << "Updating repository intro part" << endvm;
334
 
  if (!getenv ("ACNEWREPO")) {
 
254
  if (getenv ("ACOLDREPO")) {
 
255
    _vm << "Updating (old) repository intro part" << endvm;
335
256
    update_intros_in_repo (jpm);
336
257
  }
337
258
  
338
259
  jpm.setup_phase2 (*tunit, ah_trees);
339
 
  
 
260
 
 
261
  // get all class from the join point model
 
262
  ProjectModel::Selection all_classes;
 
263
  jpm.select ((JoinPointType)(JPT_Class|JPT_Aspect), all_classes);
 
264
  // update the plan for intros
 
265
  for (ProjectModel::Selection::iterator iter = all_classes.begin ();
 
266
      iter != all_classes.end (); ++iter) {
 
267
    ACM_Class &jpl = (ACM_Class&)**iter;
 
268
    link_members (jpl);
 
269
    link_bases (jpl);
 
270
  }
 
271
 
340
272
  _vm << "Weaving access control bypass classes ..." << endvm;
341
273
  insert_bypass_class (jpm);
342
274
 
343
275
  _vm << "Weaving Join Points ..." << endvm;
344
 
  Plan plan2 (_err, jpm);
345
 
  join_points (*tunit, jpm, plan2);
 
276
  join_points (*tunit, jpm, plan);
346
277
  if (_err.severity () >= sev_error)
347
278
    return false;
348
279
      
349
280
  _vm << "Final cleanup" << endvm;
350
 
  cleanup (*tunit);
 
281
  cleanup (jpm);
351
282
 
352
283
  if (_conf.dynamic ()) {
353
284
    _vm << "Preparing for dynamic weaving" << endvm;
375
306
  return (_err.severity () < sev_error);
376
307
}
377
308
 
 
309
void Transformer::determine_aspect_fwd_decls (ModelBuilder &jpm) {
 
310
  // get all aspects from the join point model
 
311
  ProjectModel::Selection all_aspects;
 
312
  jpm.select (JPT_Aspect, all_aspects);
 
313
 
 
314
  // remember that these aspects should become friend of all classes
 
315
  _aspect_fwd_decls = "";
 
316
  for (ProjectModel::Selection::iterator iter = all_aspects.begin ();
 
317
       iter != all_aspects.end (); ++iter) {
 
318
    ACM_Aspect &jpl = (ACM_Aspect&)**iter;
 
319
    _aspect_fwd_decls += "class ";
 
320
    _aspect_fwd_decls += jpl.get_name();
 
321
    _aspect_fwd_decls += ";\n";
 
322
  }
 
323
}
 
324
 
378
325
void Transformer::determine_aspect_includes (const IncludeGraph &ig) {
379
326
  // find all files that are included by aspect headers
380
327
  if (_conf.iterate_aspects ()) {
445
392
  ig.included_files (ah_unit, inc_units);
446
393
  
447
394
  // include all aspect headers that affect join points in these headers
 
395
  // and also aspect headers that affect the aspect header itself
 
396
  inc_units.insert (ah_unit);
448
397
  AspectIncludes &ais = _code_weaver.aspect_includes ();
449
398
  for (set<const Unit*>::iterator i = inc_units.begin ();
450
399
    i != inc_units.end (); ++i) {
454
403
      const set<AspectRef> &aspect_refs = aii->second;
455
404
      for (set<AspectRef>::const_iterator ari = aspect_refs.begin ();
456
405
        ari != aspect_refs.end (); ++ari) {
457
 
#ifdef ACMODEL
458
406
        ACM_Aspect &jpl_aspect = ari->_aspect->loc ();
459
 
#else
460
 
        JPL_Aspect &jpl_aspect = ari->_aspect->loc ();
461
 
#endif
462
407
        Unit *aspect_unit = TI_Aspect::of (jpl_aspect)->unit ();
463
408
        // recursively analyze the cluster of this aspect header unit
464
409
        determine_aspect_cluster (aspect_unit, ig, cluster);
481
426
    if (IntroductionUnit::cast (unit)) {
482
427
      Token *tok_before = i->_tree->token ();
483
428
      const WeavePos &before = _code_weaver.weave_pos (tok_before, WeavePos::WP_BEFORE);
484
 
      _code_weaver.paste (before, string ("/*** +access ") +
 
429
      _code_weaver.insert (before, string ("/*** +access ") +
485
430
        string (i->_info->QualName ()) + string (" ***/\n"));      
486
431
      Token *tok_after = i->_tree->end_token ();
487
432
      const WeavePos &after = _code_weaver.weave_pos (tok_after, WeavePos::WP_AFTER);
488
 
      _code_weaver.paste (after, string ("/*** -access ") +
 
433
      _code_weaver.insert (after, string ("/*** -access ") +
489
434
        string (i->_info->QualName ()) + string (" ***/\n"));      
490
435
      if (i->_tree->NodeName () == CT_MembPtrExpr::NodeId () ||
491
436
          i->_tree->NodeName () == CT_MembRefExpr::NodeId ()) {
492
437
        CTree *op = i->_tree->Son (1);
493
438
        Token *tok_before = op->token ();
494
439
        const WeavePos &before = _code_weaver.weave_pos (tok_before, WeavePos::WP_BEFORE);
495
 
        _code_weaver.paste (before, string ("/*** op ") +
 
440
        _code_weaver.insert (before, string ("/*** op ") +
496
441
          string (i->_info->QualName ()) + string (" ***/\n"));      
497
442
      }
498
443
    }
499
444
  }
500
445
  
501
446
  // mark all classes that contain dynamically introduced attributes
502
 
#ifdef ACMODEL
503
447
  ProjectModel::Selection classes;
504
448
  jpm.select ((JoinPointType)(JPT_Class|JPT_Aspect), classes);
505
449
  for (ProjectModel::Selection::iterator i = classes.begin ();
506
450
    i != classes.end (); ++i) {
507
451
    ACM_Class *cls = (ACM_Class*)*i;
508
452
    if (!cls->get_intro_target ())
509
 
#else
510
 
      JoinPointModel::Selection classes;
511
 
      jpm.select ((JoinPointLoc::join_point_type)(JoinPointLoc::Class|
512
 
        JoinPointLoc::Aspect), classes);
513
 
      for (JoinPointModel::Selection::iterator i = classes.begin ();
514
 
        i != classes.end (); ++i) {
515
 
        JPL_Class *cls = (JPL_Class*)*i;
516
 
        if (!cls->intro_target ())
517
 
#endif
518
453
      continue;
519
454
    bool mark_class = false;
520
455
    const TI_Class *ti = TI_Class::of (*cls);
527
462
      IntroductionUnit *iunit = IntroductionUnit::cast (unit);
528
463
      if (iunit) {
529
464
        mark_class = true;
530
 
#ifdef ACMODEL
531
465
        ACM_Name *jpl_aspect = (ACM_Name*)iunit->intro ()->get_parent ();
532
 
#else
533
 
        JPL_Name *jpl_aspect = iunit->intro ()->parent ();
534
 
#endif
535
466
        Token *tok_before = attr->Tree ()->ObjDecl ()->token ();
536
467
        const WeavePos &before = _code_weaver.weave_pos (tok_before, WeavePos::WP_BEFORE);
537
 
        _code_weaver.paste (before, string ("/*** +intro ") +
538
 
#ifdef ACMODEL
 
468
        _code_weaver.insert (before, string ("/*** +intro ") +
539
469
        signature (*jpl_aspect) + string (" ***/\n"));      
540
 
#else
541
 
        string (jpl_aspect->signature ()) + string (" ***/\n"));      
542
 
#endif
543
470
        Token *tok_after = attr->Tree ()->ObjDecl ()->end_token ();
544
471
        const WeavePos &after = _code_weaver.weave_pos (tok_after, WeavePos::WP_AFTER);
545
 
        _code_weaver.paste (after, string ("/*** -intro ") +
546
 
#ifdef ACMODEL
 
472
        _code_weaver.insert (after, string ("/*** -intro ") +
547
473
        signature (*jpl_aspect) + string (" ***/\n"));      
548
 
#else
549
 
        string (jpl_aspect->signature ()) + string (" ***/\n"));      
550
 
#endif
551
474
      }
552
475
    }
553
476
    if (mark_class) {
554
477
      Token *tok_before = ((CT_ClassDef*)ci->Tree ())->ObjDecl ()->token ();
555
478
      const WeavePos &before = _code_weaver.weave_pos (tok_before, WeavePos::WP_BEFORE);
556
 
      _code_weaver.paste (before, string ("/*** +class ") +
557
 
#ifdef ACMODEL
 
479
      _code_weaver.insert (before, string ("/*** +class ") +
558
480
      signature (*cls) + string (" ***/\n"));      
559
 
#else
560
 
      string (cls->signature ()) + string (" ***/\n"));      
561
 
#endif
562
481
      
563
482
      Token *tok_after = ((CT_ClassDef*)ci->Tree ())->Members ()->end_token ();
564
483
      const WeavePos &after = _code_weaver.weave_pos (tok_after, WeavePos::WP_BEFORE);
565
 
      _code_weaver.paste (after, string ("/*** -class ") +
566
 
#ifdef ACMODEL
 
484
      _code_weaver.insert (after, string ("/*** -class ") +
567
485
      signature (*cls) + string (" ***/\n"));      
568
 
#else
569
 
      string (cls->signature ()) + string (" ***/\n"));
570
 
#endif
571
486
    }
572
487
  }
573
488
}
574
489
 
575
490
 
576
491
void Transformer::update_intros_in_repo (ModelBuilder &jpm1) {
577
 
#ifdef ACMODEL
578
492
  ProjectModel::Selection intros;
579
493
  jpm1.select (JPT_Introduction, intros);
580
494
  for (ProjectModel::Selection::iterator i = intros.begin ();
587
501
  for (ProjectModel::Selection::iterator i = classes.begin ();
588
502
       i != classes.end (); ++i) {
589
503
    ACM_Class &cls = *(ACM_Class*)*i;
590
 
    // get the weaving plan of this intro
591
 
    JPP_Class *plan = (JPP_Class*)cls.plan ();
592
 
    // collect the intros into this class
593
 
    if (plan) {
594
 
      set<ACM_Introduction*> intros;
595
 
      for (int b = 0; b < plan->baseIntros (); b++)
596
 
        intros.insert (plan->baseIntro (b));
597
 
      for (int o = 0; o < plan->otherIntros (); o++)
598
 
        intros.insert (plan->otherIntro (o));
599
 
      // now update the repository with the intro information
600
 
      for (set<ACM_Introduction*>::iterator intro_iter = intros.begin ();
601
 
           intro_iter != intros.end (); ++intro_iter) {
602
 
        _repo.update (**intro_iter, cls);
603
 
      }
604
 
    }
605
 
  }
606
 
#else
607
 
  ModelBuilder::Selection intros;
608
 
  jpm1.select (JoinPointLoc::Introduction, intros);
609
 
  for (JoinPointModel::Selection::iterator i = intros.begin ();
610
 
       i != intros.end (); ++i) {
611
 
    JPL_Introduction &intro = *(JPL_Introduction*)*i;
612
 
    _repo.consider (intro);
613
 
  }
614
 
  ModelBuilder::Selection classes;
615
 
  jpm1.select ((JoinPointLoc::join_point_type)(JoinPointLoc::Class|
616
 
    JoinPointLoc::Aspect), classes);
617
 
  for (JoinPointModel::Selection::iterator i = classes.begin ();
618
 
       i != classes.end (); ++i) {
619
 
    JPL_Class &cls = *(JPL_Class*)*i;
620
 
    // get the weaving plan of this intro
621
 
    JPP_Class *plan = (JPP_Class*)cls.plan ();
622
 
    // collect the intros into this class
623
 
    if (plan) {
624
 
      set<JPL_Introduction*> intros;
625
 
      for (int b = 0; b < plan->baseIntros (); b++)
626
 
        intros.insert (plan->baseIntro (b));
627
 
      for (int o = 0; o < plan->otherIntros (); o++)
628
 
        intros.insert (plan->otherIntro (o));
629
 
      // now update the repository with the intro information
630
 
      for (set<JPL_Introduction*>::iterator intro_iter = intros.begin ();
631
 
           intro_iter != intros.end (); ++intro_iter) {
632
 
        _repo.update (**intro_iter, cls);
633
 
      }
634
 
    }
635
 
  }
636
 
#endif
637
 
}
638
 
 
639
 
 
640
 
static bool needs_friend_injection (ModelBuilder &jpm, CRecord *rec) {
641
 
  static Filename anon("<anonymous unit>");
642
 
  CSemDatabase *semdb = jpm.get_db();
643
 
 
644
 
  // no need for template instances; the templates already get the friend injection
645
 
  if (rec->isTemplateInstance())
646
 
    return false;
647
 
  // only defined classes can get an injection
648
 
  if (!rec->isDefined ())
649
 
    return false;
650
 
  // code introduced by ac++ (in an anonymous unit) is not modified here
651
 
  if (rec->Tree()->token ()->location().filename() == anon)
652
 
    return false;
653
 
  // nested classes in template instances should also not be modified to avoid double injection
654
 
  if (jpm.inside_template_instance(rec))
655
 
    return false;
656
 
  // the class has to belong to the project
657
 
  Unit *unit = (Unit*)rec->Tree ()->token ()->belonging_to ();
658
 
  if (!semdb->Project ()->isBelow (unit))
659
 
    return false;
660
 
  return true;
661
 
}
662
 
 
663
 
 
664
 
void Transformer::aspect_privileges (ModelBuilder &jpm) {
665
 
  // TODO: move this into phase 2 parse; introduce classes don't
666
 
  //       get the friend injection yet!
667
 
 
668
 
  // get all aspects from the join point model
669
 
#ifdef ACMODEL
670
 
  ProjectModel::Selection all_aspects;
671
 
  jpm.select (JPT_Aspect, all_aspects);
672
 
 
673
 
  // remember that these aspects should become friend of all classes
674
 
  list<CClassInfo*> friends;
675
 
  for (ProjectModel::Selection::iterator iter = all_aspects.begin ();
676
 
       iter != all_aspects.end (); ++iter) {
677
 
    ACM_Aspect &jpl = (ACM_Aspect&)**iter;
678
 
    friends.push_back (((TI_Aspect*)jpl.transform_info ())->ClassInfo());
679
 
  }
680
 
#else
681
 
  JoinPointModel::Selection all_aspects;
682
 
  jpm.select (JoinPointLoc::Aspect, all_aspects);
683
 
 
684
 
  // remember that these aspects should become friend of all classes
685
 
  list<CClassInfo*> friends;
686
 
  for (JoinPointModel::Selection::iterator iter = all_aspects.begin ();
687
 
       iter != all_aspects.end (); ++iter) {
688
 
    JPL_Aspect &jpl = (JPL_Aspect&)**iter;
689
 
    friends.push_back (((TI_Aspect*)jpl.transform_info ())->ClassInfo());
690
 
  }
691
 
#endif
692
 
  
693
 
  if (!friends.empty ()) {
694
 
    CSemDatabase *semdb = jpm.get_db();
695
 
    // handle struct and classes
696
 
    for (unsigned i = 0; i < semdb->ClassInfos(); i++) {
697
 
      CClassInfo *ci = semdb->ClassInfo(i);
698
 
 
699
 
      if (needs_friend_injection (jpm, ci)) {
700
 
        // perform the code transformation
701
 
        _code_weaver.declare_friends (ci, friends);
702
 
      }
703
 
    }
704
 
    // handle unions
705
 
    for (unsigned i = 0; i < semdb->UnionInfos(); i++) {
706
 
      CUnionInfo *ui = semdb->UnionInfo(i);
707
 
 
708
 
      if (needs_friend_injection (jpm, ui)) {
709
 
        // perform the code transformation
710
 
        _code_weaver.declare_friends (ui, friends);
711
 
      }
712
 
    }
713
 
  }
714
 
}
715
 
      
716
 
 
717
 
void Transformer::cleanup (CTranslationUnit &tunit) {
718
 
  CSemDatabase &db = tunit.db ();
719
 
 
720
 
  // replace keyword "aspect" with "class" and remove advice
721
 
  for (int a = 0; a < db.AspectInfos (); a++) {
722
 
    ACAspectInfo *acai = db.AspectInfo (a);
723
 
 
724
 
    // remove advice declarations
725
 
    for (int adv = 0; adv < acai->AdviceNodes (); adv++)
726
 
      _code_weaver.kill (acai->AdviceNode (adv));
727
 
 
728
 
    _code_weaver.to_class (acai);
729
 
  }
730
 
      
 
504
    // skip this class if it has no plan yet
 
505
    if (!cls.has_plan ())
 
506
      continue;
 
507
    // collect the intros into this class
 
508
    set<ACM_Introduction*> intros; // a 'set', because the same intro might add a base class and a member
 
509
    typedef ACM_Container<ACM_BaseIntro, true> BContainer;
 
510
    BContainer bintros = cls.get_plan()->get_base_intros();
 
511
    for (BContainer::iterator i = bintros.begin (); i != bintros.end (); ++i)
 
512
      intros.insert ((*i)->get_intro());
 
513
    typedef ACM_Container<ACM_MemberIntro, true> MContainer;
 
514
    MContainer mintros = cls.get_plan()->get_member_intros();
 
515
    for (MContainer::iterator i = mintros.begin (); i != mintros.end (); ++i)
 
516
      intros.insert ((*i)->get_intro());
 
517
    // now update the repository with the intro information
 
518
    for (set<ACM_Introduction*>::iterator intro_iter = intros.begin ();
 
519
         intro_iter != intros.end (); ++intro_iter) {
 
520
      _repo.update (**intro_iter, cls);
 
521
    }
 
522
  }
 
523
}
 
524
 
 
525
 
 
526
void Transformer::cleanup (ModelBuilder &jpm) {
 
527
 
731
528
  // delete all pointcut definitions that are left
732
 
  for (int p = 0; p < db.PointcutInfos (); p++)
733
 
    _code_weaver.kill (db.PointcutInfo (p)->def_node ());
734
 
}
735
 
 
736
 
 
737
 
void Transformer::introductions (CTranslationUnit &tunit,
738
 
  ModelBuilder &jpm) {
739
 
 
740
 
  // remove the introductions from the code
741
 
#ifdef ACMODEL
742
 
  ProjectModel::Selection intros;
743
 
  jpm.select (JPT_Introduction, intros);
744
 
  for (ProjectModel::Selection::iterator i = intros.begin ();
745
 
       i != intros.end (); ++i) {
746
 
    ACM_Introduction &intro = *(ACM_Introduction*)*i;
747
 
    _code_weaver.kill (TI_Introduction::of (intro)->tree ());
748
 
  }
749
 
#else
750
 
  ModelBuilder::Selection intros;
751
 
  jpm.select (JoinPointLoc::Introduction, intros);
752
 
  for (JoinPointModel::Selection::iterator i = intros.begin ();
753
 
       i != intros.end (); ++i) {
754
 
    JPL_Introduction &intro = *(JPL_Introduction*)*i;
755
 
    _code_weaver.kill (TI_Introduction::of (intro)->tree ());
756
 
  }
757
 
#endif
758
 
  
759
 
  // now delete all slice definitions
760
 
  CSemDatabase &db = tunit.db ();
761
 
  for (int s = 0; s < db.SliceInfos (); s++) {
762
 
    ACSliceInfo *acsi = db.SliceInfo (s);
763
 
    // first all members
764
 
    for (int sm = 0; sm < acsi->members (); sm++) {
765
 
      CT_Intro *member = acsi->member (sm);
766
 
      _code_weaver.kill (member);
767
 
    }
768
 
    // now the main definition
769
 
    if (!acsi->in_advice ())
770
 
      _code_weaver.kill (acsi->def_node ());
771
 
  }
772
 
}
773
 
 
774
 
void Transformer::orderings (CTranslationUnit &tunit, Plan& plan,
775
 
                             ModelBuilder &jpm, bool purge) {
776
 
 
777
 
  // let the plan object calculate the right order
778
 
  plan.order ();
779
 
 
780
 
  // remove the introductions from the code
781
 
  if (purge) {
782
 
    // Iterate through order advice declarations
783
 
#ifdef ACMODEL
784
 
    ProjectModel::Selection orders;
785
 
    jpm.select (JPT_Order, orders);
786
 
    for (ProjectModel::Selection::iterator i = orders.begin ();
787
 
       i != orders.end (); ++i) {
788
 
      ACM_Order &order = *(ACM_Order*)*i;
789
 
#else
790
 
      ModelBuilder::Selection orders;
791
 
      jpm.select (JoinPointLoc::Order, orders);
792
 
      for (JoinPointModel::Selection::iterator i = orders.begin ();
793
 
         i != orders.end (); ++i) {
794
 
        JPL_Order &order = *(JPL_Order*)*i;
795
 
#endif
796
 
      TI_Order  &ti   = *TI_Order::of (order);
797
 
      _code_weaver.kill (ti.tree ());
798
 
    }
799
 
  }
800
 
}
801
 
 
802
 
 
803
 
void Transformer::advice (CTranslationUnit &tunit)
804
 
 {
805
 
   CSemDatabase &db = tunit.db ();
806
 
   for (int a = 0; a < db.AspectInfos (); a++)
807
 
    {
808
 
      ACAspectInfo *ai = db.AspectInfo (a);
809
 
 
810
 
      _vm++;
811
 
      // handle all advice of this aspect
812
 
      for (int i = 0; i < ai->AdviceNodes (); i++) {
813
 
        CT_AdviceDecl *ad = ai->AdviceNode (i);
814
 
        CFunctionInfo *advice_func = ((CT_FctDef*)ad->Decl ())->Object ()->
815
 
          FunctionInfo ();
816
 
        
817
 
        // handle only real advice here
818
 
        if (strncmp (advice_func->Name (), "%a", 2) != 0)
819
 
          continue;
820
 
        
821
 
        // don't handle inherited advice here. This is done in the base class
822
 
        if (advice_func->BaseObject ())
823
 
          continue;
824
 
        
825
 
        _vm << ai->ClassInfo ()->QualName () << "::" 
826
 
            << advice_func->Name () << endvm;
827
 
        
828
 
        _code_weaver.declare_function (advice_func, ad); // first phase
829
 
      }
830
 
      _vm--;
831
 
    }
832
 
 
833
 
   return;
834
 
 }
835
 
 
836
 
 
837
 
void Transformer::singleton_aspects (CTranslationUnit &tunit) {
838
 
  CSemDatabase &db = tunit.db ();
839
 
  for (int a = 0; a < db.AspectInfos (); a++) {
840
 
    ACAspectInfo *ai = db.AspectInfo (a);
841
 
 
842
 
    if (ai->is_abstract ())
843
 
      continue;
844
 
 
845
 
    _code_weaver.singleton (ai);
846
 
  }
847
 
}
 
529
  ProjectModel::Selection pointcuts;
 
530
  jpm.select (JPT_Pointcut, pointcuts);
 
531
  for (ProjectModel::Selection::iterator i = pointcuts.begin ();
 
532
       i != pointcuts.end (); ++i) {
 
533
    ACM_Pointcut &pct = *(ACM_Pointcut*)*i;
 
534
    // delete all non-anonymous pointcut definitions
 
535
    if (TI_Pointcut::of (pct)->func_info())
 
536
      _code_weaver.kill (((CT_InitDeclarator*)TI_Pointcut::of (pct)->tree())->ObjDecl());
 
537
  }
 
538
}
 
539
 
848
540
 
849
541
void Transformer::insert_bypass_class (ModelBuilder &jpm) {
850
 
  set<Token*> blacklist; // see comments below
851
 
  // Iterate through classes and structs, what about unions?
852
 
#ifdef ACMODEL
 
542
  _code_weaver.bypass_info_clear();
 
543
 
 
544
  // Iterate over classes and structs, what about unions?
853
545
  ProjectModel::Selection all_classes;
854
546
  jpm.select ((JoinPointType)(JPT_Class|JPT_Aspect), all_classes);
855
547
  for (ProjectModel::Selection::iterator i = all_classes.begin ();
856
548
       i != all_classes.end (); ++i) {
857
549
    ACM_Class *cls = (ACM_Class*)*i;
858
 
#else
859
 
  ModelBuilder::Selection all_classes;
860
 
  jpm.select ((JoinPointLoc::join_point_type)(JoinPointLoc::Class|
861
 
      JoinPointLoc::Aspect), all_classes);
862
 
  for (JoinPointModel::Selection::iterator i = all_classes.begin ();
863
 
       i != all_classes.end (); ++i) {
864
 
    JPL_Class *cls = (JPL_Class*)*i;
865
 
#endif
866
 
    CClassInfo *ci = TI_Class::of (*cls)->class_info();
867
 
    Token *token = ci->DefObject ()->Tree ()->token();
868
 
    if (blacklist.find (token) == blacklist.end ()) {
869
 
      // handle all classes that are not on the blacklist
870
 
      _code_weaver.insert_bypass_class (ci);
871
550
 
872
 
      // put a class in the backlist if is defined inside a template instance
873
 
      // -> it can appear more than once in the model!
874
 
      if (jpm.inside_template_instance (ci)) {
875
 
        blacklist.insert (token);
876
 
      }
 
551
    // handle all classes that are not on the blacklist
 
552
    if (!_code_weaver.bypass_in_blacklist(cls)) {
 
553
      _code_weaver.bypass_insert (cls);
877
554
    }
878
555
  }
879
556
}
890
567
 
891
568
  _vm << "Advicecode manipulation" << endvm;
892
569
  // Iterate through advice
893
 
#ifdef ACMODEL
894
570
  ProjectModel::Selection advice_codes;
895
571
  jpm.select (JPT_AdviceCode, advice_codes);
896
572
  for (ProjectModel::Selection::iterator i = advice_codes.begin ();
897
573
       i != advice_codes.end (); ++i) {
898
574
    ACM_AdviceCode &code = *(ACM_AdviceCode*)*i;
899
 
#else
900
 
    ModelBuilder::Selection advice_codes;
901
 
    jpm.select (JoinPointLoc::AdviceCode, advice_codes);
902
 
    for (JoinPointModel::Selection::iterator i = advice_codes.begin ();
903
 
         i != advice_codes.end (); ++i) {
904
 
      JPL_AdviceCode &code = *(JPL_AdviceCode*)*i;
905
 
#endif
906
575
    TI_AdviceCode  &ti   = *TI_AdviceCode::of (code);
907
576
    // setup ThisJoinPoint object of this advice code
908
 
    ti.this_join_point ().setup (ti.function ());
909
 
    _code_weaver.provide_tjp (ti.function (), ti.this_join_point ());
 
577
    _code_weaver.setup_tjp(ti.this_join_point (), ti.function ());
910
578
  }
911
579
 
912
580
  _vm << "Collecting Advice" << endvm;
913
581
  // Iterate through advice
914
582
  _vm++;
915
583
 
916
 
  // Create a pointcut evaluator
917
584
  PointCutContext context (jpm);
918
 
  PointCutEvaluator eva (_err, context);
919
585
 
920
586
  // Create a data structure for collecting advice per join point type
921
587
  typedef list<AdviceInfo*> AdviceInfoList;
922
 
#ifdef ACMODEL
923
588
  typedef JoinPointType JPT;
924
 
#else
925
 
  typedef JoinPointLoc::join_point_type JPT;
926
 
#endif
927
589
  typedef map<JPT, AdviceInfoList> TypeAdviceMap;
928
590
  TypeAdviceMap advice_map;
929
591
 
931
593
  for (Plan::AspectContainer::iterator i = aspects.begin ();
932
594
    i != aspects.end (); ++i) {
933
595
    AspectInfo &aspect_info = (AspectInfo&)*i;
934
 
#ifdef ACMODEL
935
596
    ACM_Aspect &jpl_aspect = aspect_info.loc ();
936
 
#else
937
 
    JPL_Aspect &jpl_aspect = aspect_info.loc ();
938
 
#endif
939
597
    context.concrete_aspect (jpl_aspect);
940
598
 
941
599
    // setup thisJoinPoint for aspectOf function, if there is one
942
600
    CFunctionInfo *aspect_of_func = TI_Aspect::of (jpl_aspect)->aspectof();
943
601
    if (aspect_of_func) {
944
602
      _vm << "Setting up thisJoinPoint for aspectof" << endvm;
945
 
      aspect_info.aspectof_this_join_point ().setup (aspect_of_func);
946
 
      _vm << "Supplying aspectof() with JoinPoint and tjp if needed" << endvm;
947
 
      _code_weaver.provide_tjp (aspect_of_func,
948
 
        aspect_info.aspectof_this_join_point ());
 
603
      _code_weaver.setup_tjp(aspect_info.aspectof_this_join_point (),
 
604
          aspect_of_func);
949
605
    }
950
606
 
951
607
    // handle the advice for the current aspect
953
609
    for (list<AdviceInfo*>::const_iterator i = advices.begin ();
954
610
      i != advices.end (); ++i) {
955
611
      AdviceInfo *advice_info = *i;
956
 
#ifdef ACMODEL
957
612
      ACM_AdviceCode *code = &advice_info->code ();
958
 
#else
959
 
      JPL_AdviceCode *code = &advice_info->code ();
960
 
#endif
961
613
      CFunctionInfo *adfunc = TI_AdviceCode::of (*code)->function ();
962
614
 
963
 
#ifdef ACMODEL
964
615
      _vm << signature (jpl_aspect) << ": "  << adfunc->Name () << endvm;
965
 
#else
966
 
      _vm << jpl_aspect.signature () << ": "  << adfunc->Name () << endvm;
967
 
#endif
968
616
      _vm++;
969
617
 
970
618
      // let the pointcut evaluator create the pointcut expression object
971
619
      _vm << "Create pointcut expression tree" << endvm;
972
 
      context.func (adfunc);
973
 
      advice_info->pointcut_expr () =
974
 
#ifdef ACMODEL
975
 
      eva.create (TI_PointcutExpr::of(*code->get_expr ())->tree(), JPT_Code);
976
 
#else
977
 
      eva.create (code->expr (), JoinPointLoc::Code);
978
 
#endif
 
620
      PointCutExpr *pce = TI_Pointcut::of(*code->get_pointcut ())->get_pce ();
 
621
      context.pct_func (code->get_pointcut ());
 
622
      if (pce) {
 
623
        pce = pce->duplicate(); // create a copy of the tree. It might be inherited.
 
624
        ArgSet new_arg_bindings;
 
625
        typedef ACM_Container<ACM_Arg, true> Container;
 
626
        Container &arguments = context.pct_func()->get_args();
 
627
        for (Container::iterator i = arguments.begin (); i != arguments.end (); ++i)
 
628
          new_arg_bindings.append (*i);
 
629
        context.arg_bindings ().push (&new_arg_bindings);
 
630
        pce->semantics(_err, context);
 
631
        context.arg_bindings ().pop ();
 
632
      }
 
633
      advice_info->pointcut_expr() = pce;
979
634
 
980
635
      if (advice_info->pointcut_expr()) {
981
636
        // set the pointcut type before destroy the expression(!)
984
639
        // remember the advice for each joinpoint type that might match
985
640
        int mask = 1;
986
641
        while (mask) {
987
 
          if (mask &
988
 
#ifdef ACMODEL
989
 
              JPT_Code
990
 
#else
991
 
              JoinPointLoc::Code
992
 
#endif
993
 
              ) {
 
642
          if (mask & JPT_Code) {
994
643
            pair<TypeAdviceMap::iterator, bool> result =
995
644
              advice_map.insert (TypeAdviceMap::value_type ((TypeAdviceMap::key_type)mask, AdviceInfoList()));
996
645
            result.first->second.push_back (advice_info);
1018
667
      ++mi) {
1019
668
    JPT jp_type = mi->first;
1020
669
    AdviceInfoList &advice_info_list = mi->second;
1021
 
#ifdef ACMODEL
1022
670
    ProjectModel::Selection all;
1023
671
    jpm.select (jp_type, all);
1024
672
    for (ProjectModel::Selection::iterator iter = all.begin ();
1025
673
        iter != all.end (); ++iter) {
1026
674
      ACM_Any &jpl = (ACM_Any&)**iter;
1027
 
#else
1028
 
    JoinPointModel::Selection all;
1029
 
    jpm.select (jp_type, all);
1030
 
    for (JoinPointModel::Selection::iterator iter = all.begin ();
1031
 
        iter != all.end (); ++iter) {
1032
 
      JoinPointLoc &jpl = **iter;
1033
 
#endif
1034
675
      for (AdviceInfoList::iterator li = advice_info_list.begin ();
1035
676
          li != advice_info_list.end (); ++li) {
1036
677
        AdviceInfo *advice_info = *li;
1051
692
          _code_weaver.add_aspect_include (jp.location (), advice_info->aspect_info(),
1052
693
                                           AspectRef::AR_ADVICE);
1053
694
 
1054
 
    #ifdef ACMODEL
1055
 
          if (jpl.type_val () == JPT_Call && !jpl.get_parent()) // TODO: pseud
1056
 
    #else
1057
 
          if (jpl.type () == JoinPointLoc::MethodCall &&
1058
 
              ((JPL_MethodCall&)jpl).is_pseudo ())
1059
 
    #endif
 
695
          // if the advice uses a joinpoint ID, make sure that one is allocated
 
696
          // for the matched joinpoint
 
697
          if (TI_AdviceCode::of (advice_info->code())->this_join_point().id() &&
 
698
              !jpl.has_jpid())
 
699
            jpl.set_jpid(jpm.alloc_jpid());
 
700
 
 
701
          if (jpl.type_val () == JPT_Call && !jpl.get_parent()) // TODO: pseudo
1060
702
            continue;
 
703
 
1061
704
          // check if the context variable binding is the same for all
1062
705
          // non-pseudo join points
1063
706
          if (advice_info->binding () != binding) {
1065
708
              advice_info->binding () = binding;
1066
709
            }
1067
710
            else {
1068
 
              _err << sev_error;
1069
 
              if (expr->node () && expr->node ()->token ())
1070
 
                _err << expr->node ()->token ()->location ();
1071
 
              _err << "incompatible argument bindings in pointcut expression"
1072
 
                   << endMessage;
 
711
              _err << sev_error
 
712
                  << TI_Pointcut::of(*advice_info->code().get_pointcut())->get_location()
 
713
                  << "incompatible argument bindings in pointcut expression"
 
714
                  << endMessage;
1073
715
              // remove this erroneous advice from all lists
1074
716
              for (TypeAdviceMap::iterator i = advice_map.begin (); i != advice_map.end ();
1075
717
                  ++i) {
1087
729
  for (Plan::AspectContainer::iterator i = aspects.begin ();
1088
730
    i != aspects.end (); ++i) {
1089
731
    AspectInfo &aspect_info = (AspectInfo&)*i;
1090
 
#ifdef ACMODEL
1091
732
    ACM_Aspect &jpl_aspect = aspect_info.loc ();
1092
 
#else
1093
 
    JPL_Aspect &jpl_aspect = aspect_info.loc ();
1094
 
#endif
1095
733
    context.concrete_aspect (jpl_aspect);
1096
734
    int index = 0; // CFlow index (each CFlow has a unique index per aspect)
1097
735
 
1112
750
          const JoinPoint &jp = *iter;
1113
751
 
1114
752
          // consider this joinpoint in the big plan
1115
 
          plan.consider (jp.location (), CFlow (advice_info, index));
 
753
          plan.consider ((ACM_Code*)jp.location (), CFlow (advice_info, index));
1116
754
 
1117
755
          // remember units for inclusion of aspect headers
1118
756
          _code_weaver.add_aspect_include (jp.location (), aspect_info,
1122
760
      }
1123
761
 
1124
762
      // update the project repository
1125
 
      if (getenv ("ACNEWREPO") == 0)
 
763
      if (getenv ("ACOLDREPO"))
1126
764
        _repo.update (*advice_info, pc);
1127
765
    }
1128
766
 
1129
 
    // add order advices to plan
1130
 
#ifdef ACMODEL
1131
 
    list<ACM_Order*> orders;
1132
 
    collect_orders (jpl_aspect, orders);
1133
 
    for (list<ACM_Order*>::iterator i = orders.begin ();
1134
 
#else
1135
 
    list<JPL_Order*> orders;
1136
 
    jpl_aspect.collect_orders (orders);
1137
 
    for (list<JPL_Order*>::iterator i = orders.begin ();
1138
 
#endif
1139
 
 
1140
 
      i != orders.end (); ++i) {
1141
 
      OrderInfo *oi = plan.addOrder (jpl_aspect, **i);
1142
 
      oi->analyze_exprs (eva);
1143
 
    }
1144
 
 
1145
 
    ACAspectInfo *acai = TI_Aspect::of (jpl_aspect)->aspect_info();
1146
 
    _code_weaver.invocation_functions (acai,
1147
 
      aspect_info.ifct_decls (_code_weaver.problems ()),
1148
 
      aspect_info.ifct_defs (_code_weaver.problems ()));
 
767
    _code_weaver.insert_invocation_functions (&jpl_aspect,
 
768
        aspect_info.ifct_defs (_code_weaver.problems ()));
1149
769
  }
1150
770
  _vm--;
1151
771
 
1152
772
  _vm << "Aspect ordering ..." << endvm;
1153
 
  orderings(tunit, plan, jpm, true);
 
773
  plan.order_code_joinpoints ();
1154
774
 
1155
775
  // now do the final checks on the accumulated plan
1156
 
  _vm << "Final checks before weaving code join points" << endvm;
1157
 
  plan.check ();
 
776
//  _vm << "Final checks before weaving code join points" << endvm;
 
777
//  plan.check_code_joinpoints();
1158
778
 
1159
779
  // Don't weave if there were errors in the planning phase
1160
780
  if (_err.severity () >= sev_error)
1161
781
    return;
1162
782
 
1163
 
  char *repo_file = getenv ("ACNEWREPO");
 
783
//  char *repo_file = getenv ("ACNEWREPO");
 
784
  const char *repo_file = _conf.repository();
1164
785
  if (repo_file) {
1165
786
#ifdef _MSC_VER
1166
787
    if (!_access (repo_file, 04)) {
1168
789
    if (!access (repo_file, R_OK)) {
1169
790
#endif // _MSC_VER
1170
791
 
1171
 
      _vm << "Opening new project repository '" << repo_file << "'" << endvm;
 
792
      _vm << "Updating project repository '" << repo_file << "'" << endvm;
1172
793
      int fd = SysCall::open_excl (repo_file, O_RDWR, &_err);
1173
 
#ifdef ACMODEL
1174
794
      ProjectModel project_model;
1175
795
      XmlModelReader reader;
1176
796
      if (!reader.read (project_model, repo_file, fd)) {
1179
799
        return;
1180
800
      }
1181
801
      if (project_model.get_version () != ac_version ())
1182
 
        _err << sev_warning << "project file version differs from ac++ version"
1183
 
            << endMessage;
 
802
        _err << sev_warning << "project file version '" << project_model.get_version().c_str ()
 
803
             << "' differs from ac++ version" << endMessage;
1184
804
 
1185
805
      // merge jpm and project_mode here
1186
806
      project_model.merge (jpm);
1197
817
        "'failed" << endMessage;
1198
818
      return;
1199
819
      }
1200
 
#else
1201
 
      JoinPointModel ljpm;
1202
 
      JoinPointModel::FileOpResult res = ljpm.load (fd, repo_file);
1203
 
      if (res == JoinPointModel::JPM_LOAD_ERR) {
1204
 
        _err << sev_error << "project repository '" << repo_file << "' cannot be opened"
1205
 
        " or is invalid" << endMessage;
1206
 
        return;
1207
 
      }
1208
 
      if (res == JoinPointModel::JPM_VERSION) {
1209
 
        _err << sev_warning << "project file version differs from ac++ version"
1210
 
            << endMessage;
1211
 
      }
1212
 
      ljpm.reconcile (jpm);
1213
 
      lseek (fd, 0, SEEK_SET);
1214
 
      if (ftruncate (fd, 0) != 0)
1215
 
        perror ("truncate");
1216
 
      ljpm.save (fd, repo_file);
1217
 
#endif
1218
820
      SysCall::close_excl (fd, &_err);
1219
821
    }
1220
822
    else {
 
823
      _vm << "Creating project repository '" << repo_file << "'" << endvm;
1221
824
      int fd = SysCall::create_excl (repo_file, 0600, &_err);
1222
 
#ifdef ACMODEL
1223
 
      jpm.set_version(ac_version ());
1224
825
      XmlModelWriter writer;
1225
 
      writer.write (jpm, repo_file, fd);
1226
 
#else
1227
 
      jpm.save (fd, repo_file);
1228
 
#endif
 
826
      if (!writer.write (jpm, repo_file, fd)) {
 
827
        _err << sev_error << "saving new project file '" << repo_file <<
 
828
          "'failed" << endMessage;
 
829
        return;
 
830
      }
1229
831
      SysCall::close_excl  (fd, &_err);
1230
832
    }
1231
833
  }
1236
838
  for (TypeCheckSet::const_iterator iter = checks_false.begin ();
1237
839
       iter != checks_false.end (); ++iter) {
1238
840
    _vm << "check for " << iter->second << " in "
1239
 
        << iter->first->QualName () << " is false" << endvm;
 
841
        << signature(*iter->first) << " is false" << endvm;
1240
842
    _code_weaver.type_check (iter->first, iter->second, false);
1241
843
  }
1242
844
  const TypeCheckSet &checks_true = plan.type_checks_true ();
1243
845
  for (TypeCheckSet::const_iterator iter = checks_true.begin ();
1244
846
       iter != checks_true.end (); ++iter) {
1245
847
    _vm << "check for " << iter->second << " in "
1246
 
        << iter->first->QualName () << " is true" << endvm;
 
848
        << signature (*iter->first) << " is true" << endvm;
1247
849
    _code_weaver.type_check (iter->first, iter->second, true);
1248
850
  }
1249
851
  _vm--;
1251
853
  _vm << "Call Join Points" << endvm;
1252
854
  _vm++;
1253
855
  for (int i = 0; i < plan.call_jp_plans (); i++) {
1254
 
    JPP_Code &jp_plan = plan.call_jp_plan (i);
1255
 
#ifdef ACMODEL
1256
856
    ACM_Call &jp_loc = plan.call_jp_loc (i);
1257
857
    _vm << signature (jp_loc) << endvm;
1258
 
#else
1259
 
    JPL_MethodCall &jp_loc = plan.call_jp_loc (i);
1260
 
    _vm << jp_loc.signature () << endvm;
1261
 
#endif
1262
858
 
1263
859
    // handle call joinpoint itself
1264
 
    _code_weaver.call_join_point (&jp_loc, jp_plan);
 
860
    _code_weaver.call_join_point (&jp_loc);
1265
861
  }
1266
862
  _vm--;
1267
863
 
1268
864
  _vm << "Execution Join Points" << endvm;
1269
865
  _vm++;
1270
866
  for (int i = 0; i < plan.exec_jp_plans (); i++) {
1271
 
    JPP_Code &jp_plan = plan.exec_jp_plan (i);
1272
 
#ifdef ACMODEL
1273
867
    ACM_Execution &jp_loc = plan.exec_jp_loc (i);
1274
868
    _vm << signature (jp_loc) << endvm;
1275
 
#else
1276
 
    JPL_Method &jp_loc = plan.exec_jp_loc (i);
1277
 
    _vm << jp_loc.signature () << endvm;
1278
 
#endif
1279
869
 
1280
870
    // handle exec joinpoint itself
1281
 
    _code_weaver.exec_join_point (&jp_loc, jp_plan);
 
871
    _code_weaver.exec_join_point (&jp_loc);
1282
872
  }
1283
873
  _vm--;
1284
874
 
1285
875
  _vm << "Construction Join Points" << endvm;
1286
876
  _vm++;
1287
877
  for (int i = 0; i < plan.cons_jp_plans (); i++) {
1288
 
    JPP_Code &jp_plan = plan.cons_jp_plan (i);
1289
 
#ifdef ACMODEL
1290
878
    ACM_Construction &jp_loc = plan.cons_jp_loc (i);
1291
879
    _vm << signature (jp_loc) << endvm;
1292
 
#else
1293
 
    JPL_Construction &jp_loc = plan.cons_jp_loc (i);
1294
 
    _vm << jp_loc.signature () << endvm;
1295
 
#endif
1296
880
 
1297
881
    // handle construction joinpoint itself
1298
 
    _code_weaver.cons_join_point (&jp_loc, jp_plan);
 
882
    _code_weaver.cons_join_point (&jp_loc);
1299
883
  }
1300
884
  _vm--;
1301
885
 
1302
886
  _vm << "Destruction Join Points" << endvm;
1303
887
  _vm++;
1304
888
  for (int i = 0; i < plan.dest_jp_plans (); i++) {
1305
 
    JPP_Code &jp_plan = plan.dest_jp_plan (i);
1306
 
#ifdef ACMODEL
1307
889
    ACM_Destruction &jp_loc = plan.dest_jp_loc (i);
1308
890
    _vm << signature (jp_loc) << endvm;
1309
 
#else
1310
 
    JPL_Destruction &jp_loc = plan.dest_jp_loc (i);
1311
 
    _vm << jp_loc.signature () << endvm;
1312
 
#endif
1313
891
 
1314
892
    // handle destruction joinpoint itself
1315
 
    _code_weaver.dest_join_point (&jp_loc, jp_plan);
 
893
    _code_weaver.dest_join_point (&jp_loc);
1316
894
  }
1317
895
  _vm--;
1318
896
 
1327
905
  data._calls = 1;
1328
906
#endif
1329
907
}
 
908
 
 
909
// add references to the introduced elements to the plan
 
910
void Transformer::link_members (ACM_Class &jpl) {
 
911
  if (!jpl.has_plan ())
 
912
    return;
 
913
 
 
914
  ACM_ClassPlan *plan = jpl.get_plan ();
 
915
 
 
916
  typedef ACM_Container<ACM_Any, true> Container;
 
917
  Container &children = jpl.get_children();
 
918
  typedef ACM_Container<ACM_MemberIntro, true> Container2;
 
919
  Container2 &member_intros = plan->get_member_intros();
 
920
  for (Container::iterator i = children.begin (); i != children.end (); ++i) {
 
921
    ACM_Any *any = *i;
 
922
    if (any->type_val() == JPT_Class) {
 
923
      ACM_Class *cls = (ACM_Class*)any;
 
924
      Unit *u = (Unit*)TI_Class::of(*cls)->obj_info()->Tree()->token()->belonging_to();
 
925
      if (IntroductionUnit::cast(u)) {
 
926
        ACM_Introduction *intro = IntroductionUnit::cast(u)->intro();
 
927
        for (Container2::iterator mi = member_intros.begin ();
 
928
            mi != member_intros.end(); ++mi)
 
929
          if ((*mi)->get_intro() == intro)
 
930
            (*mi)->get_members().insert(cls);
 
931
      }
 
932
    }
 
933
    else if (any->type_val() == JPT_Function) {
 
934
      ACM_Function *func = (ACM_Function*)any;
 
935
      if (func->get_builtin())
 
936
        continue;
 
937
      Unit *u = (Unit*)TI_Function::of(*func)->obj_info()->Tree()->token()->belonging_to();
 
938
      if (IntroductionUnit::cast(u)) {
 
939
        ACM_Introduction *intro = IntroductionUnit::cast(u)->intro();
 
940
        for (Container2::iterator mi = member_intros.begin ();
 
941
            mi != member_intros.end(); ++mi)
 
942
          if ((*mi)->get_intro() == intro)
 
943
            (*mi)->get_members().insert(func);
 
944
      }
 
945
    }
 
946
  }
 
947
}
 
948
 
 
949
// add references to the introduced elements to the plan
 
950
void Transformer::link_bases (ACM_Class &jpl) {
 
951
  if (!jpl.has_plan ())
 
952
    return;
 
953
 
 
954
  ACM_ClassPlan *plan = jpl.get_plan ();
 
955
  CClassInfo *ci = TI_Class::of(jpl)->class_info();
 
956
 
 
957
  typedef ACM_Container<ACM_Class, false> Container;
 
958
  Container &bases = jpl.get_bases();
 
959
  typedef ACM_Container<ACM_BaseIntro, true> Container2;
 
960
  Container2 &base_intros = plan->get_base_intros();
 
961
  for (Container::iterator i = bases.begin (); i != bases.end (); ++i) {
 
962
    ACM_Class *cls = *i;
 
963
    // find the base class info in Puma's semantic data structure
 
964
    for (unsigned b = 0; b < ci->BaseClasses(); b++) {
 
965
      if (ci->BaseClass(b)->Class() != TI_Class::of (*cls)->class_info())
 
966
        continue;
 
967
      Unit *u = (Unit*)ci->BaseClass(b)->Tree()->token()->belonging_to();
 
968
      if (IntroductionUnit::cast(u)) {
 
969
        ACM_Introduction *intro = IntroductionUnit::cast(u)->intro();
 
970
        for (Container2::iterator bi = base_intros.begin ();
 
971
            bi != base_intros.end(); ++bi) {
 
972
          if ((*bi)->get_intro () == intro) {
 
973
            (*bi)->get_bases().insert(cls);
 
974
          }
 
975
        }
 
976
      }
 
977
    }
 
978
  }
 
979
}