<
aspect xmlns:cpp="
http://www.sdml.info/srcML/cpp"
xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsl="
http://www.w3.org/1999/XSL/Transform"
xmlns="
http://control.ee.ethz.ch/XWeaver/AspectX"
xmlns:src="
http://www.sdml.info/srcML/src"
xsi:schemaLocation="
http://control.ee.ethz.ch/XWeaver/AspectX ../../../../src/xsd/aspectX.xsd"
name="
TraceMethodLeave">
<
description>
Sample aspect program to insert tracing instructions when a selected method is
left either by return statement or by reaching end of its body.
In this example, the tracing message is output using a <
code>
printf</
code>
instruction that
writes a message to the output device stating the name of the method, the name of the class
to which it belongs and the return statement.
This aspect defines seven advices that describe seven separate but related
changes. The first two advices inserts comments to describe the changes made in the base code.
The next three advices inserts tracing instructions in the methods and the sixth advice inserts
declaration of helper variable needed for temporal storage of the return value. The last advice
inserts a new <
code>
include</
code>
statement to include the <
code>
stdio</
code>
library that is
required by the <
code>
printf</
code>
method.
<
p />
This sample aspect program targets all method definitions.
<
author>
A. Pasetti, O. Rohlik</
author>
<
see>
TraceMethodIntParameter</
see>
</
description>
<
pointcut name="
targetIntMethodImplementation"
type="
src:function"
constraint="
src:type/src:name='int'">
<
description>
Points to the implementations of the methods that must be modified. This pointcut
in particular points to methods whose return type is <
code>
int</
code>
.
This pointcut only points to the method <
i>
implementation</
i>
. A second pointcut
(<
code>
targetMethodDeclaration</
code>
) points to the method declarations.
</
description>
</
pointcut>
<
pointcut name="
targetNonIntMethodImplementation"
type="
src:function"
constraint="
src:type/src:name!='int'">
<
description>
Points to the implementations of the methods that must be modified. This pointcut
in particular points to methods whose return type is other than <
code>
int</
code>
.
This pointcut only points to the method <
i>
implementation</
i>
. A second pointcut
(<
code>
targetMethodDeclaration</
code>
) points to the method declarations.
</
description>
</
pointcut>
<
pointcut name="
targetIntMethodReturn"
type="
src:return">
<
description>
Points to return statement that must be modified. It only target return
statements that return type <
code>
int</
code>
.
</
description>
<
restriction type="
within">
<
pointcutRef ref="
targetIntMethodImplementation"
type="
src:function" />
</
restriction>
</
pointcut>
<
pointcut name="
targetNonIntMethodReturn"
type="
src:return">
<
description>
>Points to return statement that must be modified. It only target return
statements that returns other type than <
code>
int</
code>
.
</
description>
<
restriction type="
within">
<
pointcutRef ref="
targetNonIntMethodImplementation"
type="
src:function" />
</
restriction>
</
pointcut>
<!---->
<
pointcut name="
targetMethodDeclaration"
type="
src:function_decl"
constraint="
not((src:type/src:name='virtual')and(count(src:type/src:name)=2)) and not(contains(src:specifier,'='))">
<
description>
Points to all declarations of the target methods. See the description of the
pointcut (<
code>
targetMethodImplementation</
code>
).
<
p />
Note that this pointcut also excludes pure virtual declarations using examination
of the <
code>
specifier</
code>
subelement of the <
code>
function_decl</
code>
element.</
description>
</
pointcut>
<
pointcut name="
targetMethodDeclarationComment"
type="
src:comment">
<
description>
Points to the method comments that must be modified. The method comments that must
be modified are those that are followed by a <
code>
targetMethodDeclaration</
code>
pointcut. </
description>
<
restriction type="
followedBy">
<
pointcutRef ref="
targetMethodDeclaration"
type="
src:function_decl" />
</
restriction>
</
pointcut>
<
pointcut name="
targetClass"
type="
src:class">
<
description>
Points to all classes that contain a target method. The identification is done by
taking all the classes that contains a <
code>
targetMethodDeclaration</
code>
pointcut </
description>
<
restriction type="
contain">
<
pointcutRef ref="
targetMethodDeclaration"
type="
src:function_decl" />
</
restriction>
</
pointcut>
<
pointcut name="
targetClassComment"
type="
src:comment">
<
description>
Points to the class comments that must be modified. The class
comments that must be modified are those that are followed by a <
code>
targetClass</
code>
pointcut. </
description>
<
restriction type="
followedBy">
<
pointcutRef type="
src:class"
ref="
targetClass" />
</
restriction>
</
pointcut>
<
pointcut name="
targetImplementationUnit"
type="
src:unit">
<
description>
Points to all the units that contain implementations of methods that must be
modified. In srcML, a <
i>
unit</
i>
is a source file (a definition file, a declaration file, or
an inline file). This pointcut therefore identifies all the source files that contain an
implementation of the target method. </
description>
<
restriction type="
contain">
<
pointcut type="
src:function">
<
or>
<
pointcutRef type="
src:function"
ref="
targetIntMethodImplementation" />
<
pointcutRef type="
src:function"
ref="
targetNonIntMethodImplementation" />
</
or>
</
pointcut>
</
restriction>
</
pointcut>
<
advice name="
insertClassComment"
type="
end">
<
description>
Add a comment at the end of the comment of the classes that are modified by other advices.</
description>
<
pointcutRef ref="
targetClassComment"
type="
src:comment" />
<
codeModifier type="
comment">
<
text>
The implementation of this class has been modified by an aspect
program defined in TraceMethodLeave.xml. The aspect program inserts code to trace the
execution of methods. See the method comment for more details.</
text>
</
codeModifier>
</
advice>
<
advice name="
insertMethodComment"
type="
end">
<
description>
Add a comment at the end of the comment of the methods that are modified by other advices.</
description>
<
pointcutRef ref="
targetMethodDeclarationComment"
type="
src:comment" />
<
codeModifier type="
comment">
<
text>
The implementation of this method has been modified by an aspect
program. The aspect program adds a statement that prints a message to the standard output
stating (1) the name of this method, (2) the name of this class and (3) the value returned be the method.
The statement is inserted at the very beginning of the method. This message can be used to trace executions
of the method during debugging.</
text>
</
codeModifier>
</
advice>
<
advice type="
replace"
name="
insertIntTraceBeforeReturn">
<
description>
Insert the tracing instruction in the target methods. This advice inserts three instructions
in the target method.
<
p />
The first instruction evaluates the expression in the return statement and
stores the result in the helper variable. The second instruction prints the value returned by the method
(which is temporarily stored in the helper variable). The third instruction is the return statement that
returns the value stored in the helper variable. The code modifier is implemented in three steps
since the return expression may contain construction that changes it value whenever evaluated.
Therefore it is not possible to use the same expression twice -- in printf instruction and in
return statement.
<
p />
The names of the target method and target class are accessed using "dollar variables". The return expression
is accessed using XSL language instruction <
code>
xsl:value-of</
code>
.
</
description>
<
pointcutRef ref="
targetIntMethodReturn"
type="
src:return" />
<
codeModifier type="
codeFragment">
<
text>
// THREE lines below are WOVEN by ASPECT</
text>
<
xsl>
helperReturnValue = <
xsl:
value-of select="
src:expr" />
;</
xsl>
<
text>
printf("Method ${functionName} in class ${className} returns with value %d\n", helperReturnValue);</
text>
<
text>
return helperReturnValue;</
text>
</
codeModifier>
</
advice>
<
advice type="
before"
name="
insertNonIntTraceBeforeReturn">
<
description>
Insert the tracing instruction in the target methods. This advice inserts a printf
instruction at the end of the target method. The printf instruction prints the expression returned by
the function. The names of the target method and target class are NOT accessed using
"dollar variables" here. Instead the <
code>
xsl:value-of</
code>
XSLT instruction is used
to access the method name and calss name. Dollar variables cannot be used within the
<
code>
xsl</
code>
element.</
description>
<
pointcutRef ref="
targetNonIntMethodReturn"
type="
src:return" />
<
codeModifier type="
codeFragment">
<
xsl>
printf("Method <
xsl:
value-of select="
$functionName" />
in class <
xsl:
value-of select="
$className" />
returns with '<
xsl:
value-of select="
src:expr" />
'\n"); // code WOVEN by ASPECT</
xsl>
</
codeModifier>
</
advice>
<
advice type="
end"
name="
insertTraceAtFunctionEnd">
<
description>
Insert the tracing instruction in the target methods. This advice inserts a printf
instruction at the very end of every method. It may happen that the inserted function call
will be unreachable.
The names of the target method and target class are accessed using "dollar variables".</
description>
<
pointcut type="
src:function" />
<
codeModifier type="
codeFragment">
<
text>
printf("Method ${functionName} in class ${className} ends"); // code WOVEN by ASPECT</
text>
</
codeModifier>
</
advice>
<
advice type="
end"
name="
insertTraceAtContructorEnd">
<
description>
Insert the tracing instruction in the target constructor. This advice inserts a printf
instruction at the very end of every constructor.
The name of the target class is not accessed using "dollar variables" because
at the time of writing of this sample aspect dollar variables for
constructors were not implemented. As a workaround XSL
function <
code>
substring-before(src:name,'::')</
code>
is used to
query srcML for the name of of the class.</
description>
<
pointcut type="
src:constructor" />
<
codeModifier type="
codeFragment">
<
xsl>
printf("Constructor of class <
xsl:
value-of select="
substring-before(src:name,'::')" />
ends"); // code WOVEN by ASPECT</
xsl>
</
codeModifier>
</
advice>
<
advice type="
begin"
name="
insertVariableDeclaration">
<
description>
Insert the declaration of integer local variable at the beginning of target methods.</
description>
<
pointcutRef ref="
targetIntMethodImplementation"
type="
src:function" />
<
codeModifier type="
codeFragment">
<
text>
int helperReturnValue; // code WOVEN by ASPECT</
text>
</
codeModifier>
</
advice>
<
advice type="
add"
name="
addInclude">
<
description>
Add the <
code>
#include</
code>
statement for the <
code>
stdio</
code>
library.
Inclusion of this library is necessary because the code that is woven into the target methods
calls the stdio function <
code>
printf</
code>
. Note that the code to be added by this advice is
specified using the CDATA section because otherwise the braces around "stdio" would be
interpreted as XML braces by the XWeaver program.</
description>
<
pointcutRef ref="
targetImplementationUnit"
type="
src:unit" />
<
codeModifier type="
include">
<
text>
#include <stdio.h> // code WOVEN by ASPECT</
text>
</
codeModifier>
</
advice>
</
aspect>
v