Practice examples

Introduction

This section is about complete examples, explianing how to develop applications linked with the B_COMPILER library.

 

FIND_SPEC: finding specification

FIND_SPEC is part of the B_COMPILER package. It is a simple example (ako HelloWorld) of how to develop applications linked with the B_COMPILER library.
(…)

 

Some metrics

b_count is a console application writen as an example of the use of B_COMPILER as a library.

Program specifications

Presentation

b_count is a rather simple program that is able to count operations, variables, constants, and sets in a machine file (.mch). This program was writen to demonstrate the interfacing of the B_COMPILER with external programs as well as the use of certain of the B_COMPILER functions.

  • In order to interface the B_COMPILER with the program, two B_COMPILER source files need to be included.

-c_port.h : This file is a portability module that allow the use of the B_COMPILER on multiple operating systems.
-c_api.h : This file is the only client entry point of the B_COMPILER, it is therefor needed for any use of B_COMPILER functions in a program.

Variables and Classes

The classes offered by the B_COMPILER are described in the B compiler Btree manager specification 1.7 document.

Functions

Main Function

The main function of b_count is designed to print some information, initialize the compiler, and read the options that are input in the console.
The information is printed via the « cout » C++ function. The init_compiler() function initializes the compiler only the first time it is used. You can use it more than once, but it will only work the first time.

int main(int argc, char *argv[])
{
    cout << "------------------" << endl;
    cout << "Welcome to bcount!" << endl;
    cout << "------------------" << endl;

    version = get_bcomp_version();
    cout << "Bcount uses the " << version << "version of the B compiler" << endl;
    cout << endl;

    init_compiler();

The getopt function give the program the ability to read options that have been input in the console.
Depending on which option is selected the main function will clone the input arguments, read the selected machine file, create a syntaxic betree by launching the create_syntaxic_betree function, and launch the appropriate function.

char c;
while ((c = getopt(argc, argv, "ro:s:c:v:")) !=EOF)
{
   switch (c)
   {

   /* more code here */

   case 'v' :
   {
       clone(&file_name, optarg);
       create_syntaxic_betree();
       count_variables();

       return 1 ;
   }
   default :
   {
       cout << "Il existe cinq options/There are five options:" << endl;
       cout << "-r: Ne rien faire/Do nothing" << endl;
       cout << "-o: Compter le nombre d'operation dans le fichier machine cible/count the number of operations in the target machine file" << endl;
       cout << "-v: Compter le nombre de variables dans le fichier machine cible/count the number of variables in the target machine file" << endl;
       cout << "-c: Compter le nombre de constantes dans le fichier machine cible/count the number of constants in the target machine file" << endl;
       cout << "-s: Compter le nombre d'ensembles dans le fichier machine cible/count the number of sets in the target machine file" << endl;
       return 1 ;
   }
  }
}

The count functions

There are four functions designed to count the operations, variables, constants, and sets in the b_count program that all work in the same way.
Here we will consider the count_operations function.
The get_root function is called in order to access the root of the previously created syntactic betree. This function returns the instance of T_machine that describes the component. In the case of the count_operations function, the get_operations method is called in order to access all the operations in the selected machine file.

void count_operations(void)
{
    int i = 0;
    root = syntaxic_betree->get_root();
    cout << "get machine root... done" << endl;
    ops = root->get_operations();
    cout << "get operations... done" << endl;

The first operation is submitted to the is_an_operation method which returns TRUE if the instance is an operation, in which case an int variable i is incremented. The get_next method then allows us to read the next operation. The process is repeated until the get_next method returns NULL, meaning that there are no more operations in the files.

if(ops != NULL)
    {
        if(ops->is_an_operation() == TRUE)
        {
            i++;
        }
        cur_item = ops->get_next();
        while(cur_item != NULL)
        {
            if(cur_item->is_an_operation() == TRUE)
            {
                i++;
            }
            cur_item = cur_item->get_next();
        }
    }
    cout << "get operations count... done" << endl;
    cout << endl;

The variable i is then printed in the console, indicating the precise number of operations in the selected machine file.

    cout << "there is/are " << i << " operation(s) in selected machine";
}

The count_variables, count_constants, and count_sets functions work in a similar manner.

The create_syntaxic_betree function

This function uses the syntaxic_analysis function of the B_COMPILER to create a syntaxic betree, the function then verifies the betree state by means of the get_status method. Upon a succesfull betree creation, a message is printed in the console.

T_betree create_syntaxic_betree(void)
{
    syntaxic_betree = compiler_syntax_analysis(file_name);
    status = syntaxic_betree->get_status();
    if (status == BST_SYNTAXIC)
    {
        cout << "syntaxic analysis... done" << endl;
        cout << "make syntaxic betree... done" << endl;
    }
    return *syntaxic_betree;

}

Example: b_count

Download b_count source here. Note: in order for this program to work you must have compiled the B_COMPILER sources. Here are some machine files that will allow you to test b_count.

IDE Configuration

In order to use the B_COMPILER as a library you will most likely need to configure your IDE. Here is a step by step indication of how to configure Code::Blocks to construct this example program:

  • Build a new project (file>new>project). If you intend to build this example application select « console application ». Click on « go »
  • Select language (C or C++) and click on « next »
  • Input project directory and click on « next »
  • Select compiler (Cygwin GCC compiler was used…) and click on finish.
  • You should then be able to read and write in a source file called main.cpp in your project. Replace it’s contents by those of the b_count source file.
  • Next, you need to configure the build options (project>build options…):

-In « linker settings » you need to add the paths to the B_COMPILER libraries (they are in the b_compiler_sources_1.0/AB/blib/OS/ directory). There should be three libraries: libBCOMP.a, libRES.a, and libSTUB_DECOMP.a
-In « Search Directories », in the « compiler » tab, you need to add the path to the b_compiler_sources_1.0/B_COMPILER directory.

  • Once this is done, rebuild the project and compile it.

Use

B_count is a simply used program. Go to b_count.exe directory in the console, then input the following in console depending on what you intend to do, in order to use b_count you need to have a machine file:

./b_count.exe -o /path/file.mch  ==> count operations
./b_count.exe -v /path/file.mch  ==> count variables
./b_count.exe -c /path/file.mch  ==> count constants
./b_count.exe -s /path/file.mch  ==> count sets
./b_count.exe -n /path/file.mch  ==> do nothing

If you type anything else, the default message will apear indicating the different options that are available.