Recent News
- [August 7, 2009] Website published!
Functionality
Aspicere is an aspect language for C with the following characteristics:
- an aspect module is a normal C compilation unit enhanced with an advice construct
- expressive pointcut language based on Prolog, enabling:
- generic advice (reuse!)
- access to and manipulation of join point context
- access to weave-time metadata and -rules such as the current build configuration and
annotations (
/*@some_tag(field1,field2)*/
)
- supported join points:
- call ("invocation"), execution and delimited continuation join points
- preliminary support for
cflow
sequence
-like temporal pointcuts- join point properties can be attached to join points (similar to inter-type declaration)
- advice code is similar to procedures, except that:
- it can use typed variables bound in the pointcut (so-called "bindings")
- around advice can contain a
proceed
-call
- two weaver implementations:
- compile-time weaver which supports limited version of Aspicere (Aspicere1)
- fully functional link-time weaver with optimization facilities, based on LLVM (Low-Level Virtual Machine) (Aspicere2)
Code Examples
We give two simple code examples, followed by a more complex one.
1. Recovery aspect
This first example aspect checks whether a critical SQL query (call to _iqcftch
) has been
interrupted by a database error. If the particular error which popped up is recoverable, the aspect
tries to fix the error up to a maximum number of attempts. If the error still persists, an
error-specific message is prompted. This example works for Aspicere1 and Aspicere2, but with a slightly
different syntax.
#include <stdio.h> #include "sql.h" int recover(int ErrorCode, int Iterations, char* ErrorString) around Jp: invocation(Jp,"_iqcftch",_) && critical_call(Jp) && sql_redo(ErrorCode,Iterations) && sql_code(ErrorCode,ErrorString) { int res=0; int i; for(i=-1;i<Iterations;i++){ res=proceed(); if(sql_code==ErrorCode){ if(i<Iterations-1) { if (i == -1) fprintf(stderr,"!! Error (%d): %s\n", ErrorCode, ErrorString); fprintf(stderr,"!! Retrying (attempt %d/%d)...\n",(i+2), Iterations); } else { fprintf(stderr,"Retry limit reached. Bailing out.\n"); } } else { if (i > -1) fprintf(stderr,"!! Retry %d was successful.\n", (i+1)); break; } } return res; }
Of course, the notion of "a critical SQL query" is subject to interpretation. Developers can annotate queries, or use Prolog facts and rules for this. Here, we use the latter approach:
:- load_library('KnowledgeLibrary').
sql_code(-666,'The statement cannot be executed, because a time limit was exceeded.').
sql_code(-910,'The object cannot be used, because an operation is pending.').
sql_code(-542,'Invalid SQL code.').
sql_code(-357,'The file server is currently not available.').
sql_redo(-666,2).
sql_redo(-357,3).
sql_redo(-542,0).
critical_method('monthlyPayment').
critical_call(Jp) :-
enclosingMethod(Jp,EncMethod),
execution(EncMethod, Name),
critical_method(Name),
print('CRITICAL call found!!!'),nl.
2. Optimizer aspect
In this example, we optimize an SQL-query by modifying the argument of the call to _iqcprep
.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "sql.h" #define CRITICAL_FREQ 2 /* Usage patterns */ static int usage=0; static char* last_query=0; static void cleanup(void){ if(last_query) free(last_query); } static char* getLastQuery(void){ if(!last_query) atexit(cleanup); return last_query; } static void setLastQuery(char* new_query){ if(last_query) free(last_query); last_query=(char*)malloc((strlen(new_query)+1)*sizeof(char)); strcpy(last_query,new_query); } /* Optimize SQL queries based on usage patterns */ void optimise_query (char* Query) before Jp: invocation(Jp,"_iqcprep") && args(Jp,[Query|_]) { char* optimised_query=0; if(getLastQuery()&&!strcmp(getLastQuery(),Query)){ /* Same query */ usage++; if(usage<=CRITICAL_FREQ) { /* Suboptimal optimizing */ optimised_query=(char*)malloc((strlen(Query)+9+1)*sizeof(char)); strcpy(optimised_query,"OPTIMISED"); strcat(optimised_query,Query); }else{ /* Optimal optimizing */ optimised_query=(char*)malloc((strlen(Query)+14+1)*sizeof(char)); strcpy(optimised_query,"SUPEROPTIMISED"); strcat(optimised_query,Query); } printf("--Unoptimised query:\t%s\n",Query); Query=optimised_query; printf("++Optimised query:\t%s\n",Query); }else{ setLastQueryQ(Query); usage=1; printf("--Could not optimise query yet.\n"); } }
3. Delimited Continuation Join Point
This more complex example illustrates the concept of delimited continuation join points and Aspicere2's annotation support.
First, we show the base code.
#include <stdio.h>
int g(void){
return 0;
}
void f(void){
printf("B");
/*@halting()*/
g();
printf("C");
}
int main(void){
printf("A");
f();
printf("D\n");
}
The /*@halting()*/-annotation means that we want to stop the
execution of procedure f
if the call to g
returns zero (which is always true
here for the sake of simplicity). In other words, printf("C")
must NOT be executed. For
this, we need the following advice:
int handling (int* ReturnVal) around Jp:
halting_invocation(JpCall,ReturnVal)
&& delimited_continuation(Jp,JpCall) {
if(*ReturnVal==0)
return *ReturnVal;
else
return proceed();
}
This advice does the following: if the return value of a /*@halting()*/-annotated call equals zero, the delimited continuation (i.e. the remaining execution within procedure f after the call to g) is skipped (not proceeded). Otherwise, the remaining execution is resumed (proceeded). In other words, we get "ABD" as output.
How do we define the halting_invocation/2 predicate? For this, we need to attach a join point property to procedure f
in order to
temporarily store the return value of /*@halting()*/-annotated
calls:
int* return_var () on Jp:
execution(Jp,_);
void var_update(int* ReturnVal) after Jp returning (int* Result):
halting_invocation(Jp,ReturnVal){
*ReturnVal=*Result;
}
Finally, this is the actual definition of the halting_invocation/2 predicate:
halting_invocation(JpCall,ReturnVal):- invocation(JpCall,_), annotation(JpCall,halting,_) enclosingMethod(JpCall,JpEncl), property(JpEncl,return_var,ReturnVal) .
Basically, there is a check whether JpCall
is a call annotated with a /*@halting()*/ annotation. If so, the current value of the return_var property attached to the calling execution join point
property is returned.
In this paper, we apply delimited continuation join points to extract an idiom-based exception handling idiom into aspects.
Releases
There are two implementations of Aspicere. Aspicere2 fully implements Aspicere, whereas Aspicere1 only provides a small subset.
Aspicere1
Beta 1 is the aspect weaver we used in the Kava case study. This means that it is able to weave in K&R- as well as in ANSI C-code. Unfortunately, in the former case, there are times when method prototypes don't declare the types of their arguments. Aspicere1 infers these types from a procedure's call site, but does not support all possible C types. In those cases, our weaver merely "skips" the relevant join points without halting the full weaving process. The weaver shows statistics about the relative percentage of "skipped" join points.
Aspicere1 has the following limitations:
- only supports call join points
- (with GCC 4.x on non-OSX platforms) modifying captured arguments of advised procedures gives a compilation error
- does not advize function pointers
- multiple advices on the same join point are allowed, but advice on advice is not possible yet
As a manual workaround for the GCC 4.x bug, one can do the following:
- open the file which refuses to compile
- regexp-replace all "# .*" (mind the space) by ""
- retry the offended GCC command and note down the erring line numbers
- reopen the file which refuses to compile
- go to the relevant lines and replace the casts like
(char*)voidptr=charptr;
byvoidptr=(void*)charptr;
- recompile the corrected file
Aspicere1 is covered under a Tri License scheme: MPL/LGLP/GPL. It depends on Yerna Lindale and Lillambi, but these are included in the download. Furthermore, you need a Java 1.4-compatible VM, a C compiler, Perl interpreter and Bash shell. The included INSTALL file contains detailed installation instructions for Aspicere1.
Aspicere2
Aspicere2 is also covered under a Tri License scheme: MPL/LGLP/GPL. It has the following dependencies:
- recent Linux or OSX with Perl
- LLVM 2.3
- DejaGNU, Expect and TCL
- SWI Prolog
- Boost.regex 1.33.1
- [OPTIONALLY] Doxygen
This is the most recent version of Aspicere2, used in multiple papers. The best documentation can be found here. The included INSTALL file contains installation instructions for all of these and for Aspicere2 itself.
Publications
- HAUPT, M., ADAMS, B., TIMBERMONT, S., GIBBS, C., COADY, Y. and HIRSCHFELD, R. (2009). Disentangling Virtual Machine Architecture, in IET Software: Special Issue on Domain-specific Aspect Languages, 3 (3), pages 201-218, IET. BibTeX
- ADAMS, B., DE SCHUTTER, K., ZAIDMAN, A., DEMEYER, S., TROMP, H. and DE MEUTER, W. (2009). Using Aspect Orientation in Legacy Environments for Reverse Engineering using Dynamic Analysis - An Industrial Experience Report, Journal of Software and Systems (JSS), 82 (4), pages 668-684, ISSN: 0164-1212, Elsevier. BibTeX
- ADAMS, B., DE MEUTER, W., TROMP, H. and HASSAN, A. E. (2009). Can we Refactor Conditional Compilation into Aspects?, in Proceedings of the 8th ACM international conference on Aspect-oriented Software Development, AOSD (Charlottesville, VA, US), pages 243-254, ISBN-ISSN: 978-1-60558-442-3, ACM, March 2009. (Acceptance ratio: 19/86=22%) BibTeX (Most Influential Paper Award)
- ADAMS, B. (2008). Co-evolution of Source Code and the Build System: Impact on the Introduction of AOSD in Legacy Systems, PhD dissertation, 353 p., ISBN 978-90-8578-203-2, Ghent University, Belgium, May 2008. BibTeX
- ADAMS, B., HERZEEL, C. and GYBELS, K. (2008). cHALO, Stateful Aspects in C, in Proceedings of the 7th Workshop on Aspects, Components, and Patterns for Infrastructure Software, ACP4IS (Brussels, Belgium), pages 1-6, ISBN: 978-1-60558-142-2, ACM, March 2008. BibTeX
- DE SCHUTTER, K. and ADAMS, B. (2007). Aspect-orientation For Revitalising Legacy Business Software, in Proceedings of the ERCIM Working Group on Software Evolution (06-07 April 2006, Lille, France), Electronic Notes in Theoretical Computer Science (ENTCS), 166 (1), pages 63-80, Elsevier. BibTeX
- ADAMS, B. and DE SCHUTTER, K. (2007). An Aspect for Idiom-based Exception Handling (using local continuation join points, join point properties, annotations and type parameters), in Proceedings of the 5th Software-Engineering Properties of Languages and Aspect Technologies Workshop, SPLAT (Vancouver, Canada), pages 1-8, ISBN: 1-59593-656-1, ACM, March 2007.(presentation)(poster) BibTeX
- ZAIDMAN, A., ADAMS, B., DE SCHUTTER, K., DEMEYER, S., HOFFMAN, G. and DE RUYCK, B. (2006). Regaining Lost Knowledge through Dynamic Analysis and Aspect Orientation - An Industrial Experience Report, in Proceedings of the 10th European Conference on Software Maintenance and Reengineering, CSMR (Bari, Italy), pages 91-102, IEEE Computer Society, March 2006. (Acceptance ratio: 27/65=42%) BibTeX