Friday, October 26, 2012

Get Rid Of MACRO Complexity When Tracing API Sources

     In C/C++ projects sometimes there are too many definitions and macro used. This is usually done to  add a layer between library sources and user implementation. Sometimes it is used to use template approach in C sources by "ifdef" and other similar preprocessors as below.

        /* unsigned integer multiplication in mul_ui.c */

        #define OPERATION_mul_ui
        #include "mul_i.h"

        /* signed integer multiplication in mul_si.h */

        #define OPERATION_mul_si
        #include "mul_i.h"

        /* mul_i.h */

        #ifdef OPERATION_mul_si
        #define FUNCTION               mpz_mul_si
        #define MULTIPLICAND_ABS(x)    ((unsigned long) ABS(x))

        #ifdef OPERATION_mul_ui
        #define FUNCTION               mpz_mul_ui
        #define MULTIPLICAND_UNSIGNED  unsigned
        #define MULTIPLICAND_ABS(x)    x
        #ifndef FUNCTION
        Error, error, unrecognised OPERATION

        void FUNCTION (mpz_ptr prod, mpz_srcptr mult,
                                MULTIPLICAND_UNSIGNED long int small_mult)
              /* ..... */

    At that time it is difficult to trace API sources and generally we lose our-self in definitions. Nowadays I use MPIR library which is common library for big numbers arithmetic and calculations. I need to trace API functions source codes and use functions implementations directly as inline into my own source codes in order to remove libraries function call costs. However there are plenty of definitions for types, functions, constants etc. As you know when compiler run, preprocessor is called at first and when processor finished its job then compiler starts to compile sources.

    In order to cope with that MACRO definitions complexity we can run gcc and tell him just run preprocessor and then exit without compiling sources. With "-E" parameter gcc does exactly what we need:

         gcc -E main.c > main_proprocessed.c