#################### English README #################### 

########## Why such a strange name ##########  

  The name of this MELT module is Talpo. This means mole (the animal) in
Esperanto (the international language). The idea below this name is that we can
travel through GCC as moles burrow: they are quite blind but still can find
food (as we find useful informations).

########## What can you really do Talpo ##########  

  The idea of Talpo is to offer to the user various way to insert tests on his
code using the GCC machinery. Talpo can be used by inserting pragmas in the
code, by giving direct argument to GCC or through the use of a file. This is
possible to insert new way to give arguments to Talpo as detailed later.

  For the moment tests can only be run at GIMPLE state, but we could
imagine to enlarge this later. This means that a test is launched successively
on each function of the file you are compiling. The main inconvenient is that
each pass is run with a function scope (so we cannot do tests on a global
scope or using nested function calls).

  The kinds of tests that we can actually run are the following:
    * Testing that the result of a call to a function is tested immediately to
      be (not) NULL, zero, or negative.
    * Testing that a call to a given function is (not) immediately followed by a
      call to another function.
    * Testing that a call to a given function is followed in the same function
      body by a call to another function.
    ...

    Talpo has mainly be tested on C source code, it does not work correctly with
    C++ because of mangling problem (transformation of the name of class
    variables and functions). This might be easily changed with future release
    of GCC and MELT (see AdvancedREADME for more information). Talpo has never
    been tested for other languages, but has it mainly works on an intermediate
    representation which is generic to the different possibles front-end of GCC,
    so it might not impossible to have it working.

########## A few words about used terms ##########

  To avoid using to often the word 'test' without much sense, I will speak of a
  'test model' for a generic Talpo test, which should be instantiated with user
  given arguments. I will use the word 'test' alone to speak of an user
  instantiated 'test' which he want to run on his code.

  TestNull is a 'test model'

  (TestNull fopen) is a 'test' as a particular use of TestNull 'test model'.


########## INSTALL ##########

  Talpo uses MELT (http://gcc-melt.org/) and so, you must have GCC and MELT
installed. You can install MELT both as a GCC branch or as a GCC plugin, the
most simple is to take the plugin version, as it does not need to compile a full
GCC.

  Talpo works on GNU/Linux, it has not been tested on others systems. GCC
  plugins does not work under Windows, MELT might also have GNU/Linux specific
  development and might not work on others Unix.

  To use Talpo, you should compile it's sources into severals .so files.
  You should be able to do so, by using the given Makefile (or Makefile-plugin
if you use MELT as a plugin):
  So you just have to run:
  'make'

  If you want to install Talpo, you can then enter:
  'make install'

########## Different versions of Talpo ##########

  As Talpo uses very recent version of GCC and MELT there are several versions
  available:
    * Talpo_GCC-4.6_MELT-0.8 : This release has a quite limited pragma
      handling and might be slower than a version using MELT-0.9 and would never
      work with C++.
    * Talpo_GCC-4.6_MELT-0.9 : This release has a quite limited pragma
      handling.
    * Talpo_MELT-0.8: This release might be slower than a version using MELT-0.9
    and would never work with C++.
    * Talpo_MELT-0.9: This release is the most updated.

  All those versions are available on https://gitorious.org/talpo/talpo in
  different branches.
    Note: Talpo does not run under a version of GCC lower than 4.6 !
  
########## Running Talpo ##########
  
  Once, you have installed Talpo, you can use it when compiling a given project.
  You will typically call GCC that way (with MELT as plugin):

	gcc -Wall fplugin=melt.so -fplugin-arg-melt-mode=talpo  \
-fplugin-arg-melt-module-path=$(TalpoModulePath) \
-fplugin-arg-melt-extra=@$(TalpoModlisPath)/talpo \
  -O0 test.c -o test.o


  -fplugin precises the GCC plugin we are using.
  -fplugin-arg-melt-mode precises the MELT mode we are using.
  -fplugin-arg-melt-module-path precises the path where to find Talpo .so files.
  -fplugin-arg-melt-extra is needed to import *.so files (it uses a .modlist
  file).
  -fplugin-arg-melt-option is a way to pass arguments to a MELT module.

  Variable $(TalpoModulePath) points to the directory containing the differents
  Talpo .so files.
  Variable $(TalpoModlisPath) points to the directory containing the .modlis
  files. Those files lists every module that needs to be loaded to run Talpo.
  Generally TalpoModlisPath = $(TalpoModulePath).

  You should not use -g when running Talpo tests (as it modify internal
  representation in a way that Talpo actually does not handle). It mights be
  better to compile without optimisation -O0 but should works in most case with
  -O2.


########## Running Talpo and inserting your tests ##########
  
  In the previous part, you just run Talpo without inserting any tests, so it
  will not parse code and add warnings.

  To really use Talpo, you have various way to insert your tests:

  * Using direct argument:
    When invoking GCC with talpo plugin you can insert a line such as the
    following to directly invoke the test model:

    -fplugin-arg-melt-option='talpo-arg=(testNull "fopen")(testFollowedBy "pthread_mutex_lock" 1, "pthread_mutex_unlock" 1)'

    Each argument is given as an s-expression, this means that you first
    open a parenthesis, you put an 'operator' first (in the case of Talpo, it
    should be a test model, such as 'testNull' or 'testImmediatlyFollowedBy').
    The next arguments are arguments of the operator. Here '"fopen"' means you
    want to check that fopen is followed by a test on his returned pointer. The
    number of argument is depending of the test you are running. Those
    arguments must be a C string, this just means for you that you have to put
    '"' around your arguments.

    This one add a test testing that the returned pointer of a call to fopen is
    followed by a test to check that it is (not) NULL. The second test checks
    that each call to pthread_mutex_lock is followed in the same function body
    by a call to pthread_mutex_unlock on the same first argument (that the role
    of the '1').

    Passing direct argument is quite a bad solution and should be used only when
    discovering Talpo: Using it in Makefile, configure and script will make you
    crazy because of the different conflicting quotes.

  * Using a file containing the different tests.
    When invoking GCC with Talpo module, you can insert a line such as the
    following giving a file path:

    -fplugin-arg-melt-option='talpo-arg-file=myFilePath.melt'

    The syntax is the same as the one used by direct argument, so you could have
    the following file content :

      (testNull "fopen")
      (testFollowedBy "pthread_mutex_lock" 1, "pthread_mutex_unlock" 1)

    This solution is quite good and easy to use.

  * Using pragma in your code
    
    In The file you want to compile, you can directly add pragma. If you have a
    version of GCC superior (strictly) to 4.6 (and the corresponding Talpo
    release), you benefit of a full plugin pragma support and can insert the
    following in your file:

    #pragma MELT Talpo testZero(fopen)
    #pragma MELT Talpo testFollowedBy(pthread_mutex_lock, 1, pthread_mutex_unlock, 1)

    If you are using a version equal or inferior to 4.6, there is a single
    pragma name for MELT which is shared by the different modules:

    #pragma GCCPLUGIN melt testNull(fopen) 
    #pragma GCCPLUGIN melt testFollowedBy(pthread_mutex_lock, 1, pthread_mutex_unlock, 1)

    As you see the syntax does not use s-expression, this is because it follows
    the classical pragma format: operator followed by his argument between
    parenthesis and comma separated.
    Using pragma is a good way if you expect to run Talpo quite often when
    compiling the source file.

########## The different files ##########
  Talpo is separated in many files, the idea is that each file correspond to
one main need, so it is easy to add or delete files. The goal would be that
when you want to add something (a new test model or a new way for the user to
use the plugin) you would only have to add one file without modifying anything
else.
 
  talpo_init_test.melt:
    This file contains the info which are needed to declare a test and some
    general functions which might serve in many tests. This is the first file
    compiled.

  talpo_dispatcher.melt:
    This is the core file as it convert the different tests into GCC pass. This
    is the main file executed when using the plugin, so at the end of this file
    there is the different instructions to read from front-ends and to start the
    plugins.

  talpo_test_*.melt:
    Thoses files contains the different possible tests. They use
    talpo_init_test.melt.

  talpo_arg_*.melt:
    Each file represent a way for the user to give a list of tests.

########## Exhaustive list of possible test Models ########## 
  Each test model can be call with the following format (except for pragma
							 handling):
    (myTest firstArg [firstPosNumber] secondArg [secondPosNumber]...)
 
  When using pragma the format is the following:
    myTest ("firstArg", [firstPosNumber,] "secondArg", [secondPosNumber,] ...) 

  myTest is a string referring to a registered test model.

  XXXArg is a string referring a function.

  XXXPosNumber is an optional integer referring to the position of an argument
  of function XXXarg on which we want to focus. For example if you test that a
  malloc call is followed by a call to free, you would like them to be checked
  accordingly to their first arguments so you will use:
    (testFollowedBy "malloc" 1 "free" 1)

  If you don't precise an XXPosArg, the default used is 0 (which stand for the
  variable returned by the function.

  You might also want to use -1 if you want to check for each use of the
  function without looking at a precise variable.

  CAUTION: You have to declare 0 or each XXXPosNumber, you cannot just declare
  one posNumber if your function takes 2 or more XXXArgument.

  Here is the list of available test models:
  
  * testNull: take 1 argument (+1 optionnal PosNumber), it checks that returned
    pointer of function given as argument is tested to be (or not) null.
  * testZero: take 1 argument (+1 optionnal PosNumber), it checks that returned
    integer of function given as argument is tested to be (or not) equal to 0.
  * testNeg: take 1 argument (+1 optionnal PosNumber), it checks that returned
    integer of function given as argument is tested to be (or not) inferior to
    zero.
  * testSumple: take 1 argument (+1 optionnal PosNumber), it checks that
    result of the function is tested (without verifying the kind of test).

  * testImmediatlyFollowedBy: take 2 arguments (+2 optionnal PosNumbers), it
    checks that a call to the first given function is immediately followed by a
    call to the function given as second argument.
  * testNotImmediatlyFollowedBy: take 2 arguments (+2 optionnal PosNumbers), it
    checks that a call to the first given function is not immediately followed
    by a call to the function given as second argument.

  * testFollowedBy: Take 2 arguments (+2 optionnal PosNumbers), it checks
    that a call to the first given function is followed in the same function
    body by a call to the function given as second argument.

########## Writting new Test Model ##########

  This is pretty easy to write a new test model , you can integrate it without
  making any change in others source files:

    * Create a new MELT file starting by "talpo_test_".
    * Create one or several instances of class_talpo_test_model, giving some
      basic informations about the test model (you can look in
      talpo_init_test.melt where the class is defined or in others tests files).
      This makes sense to declare more than one class_talpo_test_model only when
      you have very related test model, such as testNull, testZero, testNeg
      which are the same with only a small difference.
    * writing the handler as a usual pass execution function. It takes one
      argument which is the current pass being run. The field :gccpass_data of
      the pass contains an instance of class_talpo_test allowing to recover
      argument and position Argument.

    Have a look at the others test model files to see how it is done.

    When your test model is written, you just have to run 'make' a new time,
    your file will be compiled and properly integrated into Talpo.

    MELT has 3 compilations mode (translatetomodule, translatequickly,
    translatetodebug), the default mode for compiling Talpo is
    translatetomodule but you can change it (especially if you need to debug
    your test models), for this you have to set an environment variable
    TALPO_MELT_MODE to the desired mode.

########## Writing a new Front-End ##########

  Front-ends are the different ways for the user to insert his tests.
  Front-end are available in files talpo_arg*. It is possible to write a new
  Front-end and it does not need to change extra-file:
  
    * Create a new MELT file starting by "talpo_arg_".
    * Create one instance of class_talpo_frontEnd, giving some basic
      informations about the Front-end (you can look in talpo_init_test.melt
      where the class is defined or in others Front-end files.
    * The instance must contain a closure in the field :talpo_frontEnd_closure
      which allows to call a function registered the Front-end.

    Have a look at the others "talpo_arg_*" files to see how it is done.

    When your Front-End is written, you just have to run 'make' a new time, your
    file will be compiled and properly integrated into Talpo.

    MELT has 3 compilations mode (translatetomodule, translatequickly,
    translatetodebug), the default mode for compiling Talpo is
    translatetomodule but you can change it (especially if you need to debug
    your Front-end), for this you have to set an environment variable
    TALPO_MELT_MODE to the desire mode.

########## Contributors ########## 
  Pierre Vittet: Main developper
  Alexandre Lissy: Contribution to the makefile and installation system.
  Guillaume Smaha: Contribution to the makefile and Talpo bugs with MELT 0.8.

########## Special Thanks ########## 
  Thanks to Basile Starynkevitch, the MELT creator for his help and support.
  Thanks to my college supervisors (Alexandre Lissy and Patrick Martineau), for
  their support and confidence.
  Thanks to the GCC community for accepting the project and answering my
  questions.
  Thanks to Google, for accepting the project and for their financial support.
  Thanks to Polytech Tours, my college, for giving me time and confidence for
  the project.

