cpplint – C/CPP mixed-mode parser

DESCRIPTION

cpplint is a tool which prepares unpreprocessed C code for analyzing it with lint-like tools. The main purpose of cpplint tool is to find all possible preprocessing pathes of the code.

Consider the code [example.c]:

#if defined(A)
#   define FOO(a) a + a
#elif defined(B)
#   define FOO(a) a * a
#else
#   define FOO(a) a % 2
#endif

int main(int argc, char *argv[]) {
    int a = 10;
    return (FOO(a));
}

Let's consider all the possible variants of preprocessor's input values which can change the result of preprocessing of "example.c"

%cpp -UA -UB example.c
int main(int argc, char *argv[]) {
    int a = 10;
    return (a % 2);
}

%cpp -DA -UB example.c
int main(int argc, char *argv[]) {
    int a = 10;
    return (a + a);
}

%cpp -UA -DB example.c
int main(int argc, char *argv[]) {
    int a = 10;
    return (a * a);
}                

As we can see from the example, different input values produce different code. The main goal of cpplint is to list a set of all possible input values which would influence on preprocessor's output. Each macro/value combination we call as preprocessing path. "example.c" produces 3 preprocessing pathes.

cpplint is written in C, with using of flex for input tokenization and D parser for definition of mixed C/CPP grammar an building an Abstract Syntax Tree (AST).

INTERNALS

cpplint consists of 3 physical parts which can be also used separately.

cpplint

This is the main application which lists all the preprocesisng pathes. This application uses cppdast for getting a mixed C/CPP AST from input file.

cppdast

This program creates an AST using cppscan output. AST can be saved in a file for future manipulations.

An example of usage:

% ./cppscan example.c | ./cppdast -p -o example.ppl
[type: 6000, value: MAIN_NODE]
child:
      [type: 5980, value: IF_NODE]
      args:
            [type: 337, value: TDEFINED]
            args:
                  [type: 267, value: A]
      child:
            [type: 5970, value: IFBODY_NODE]
            child:
                  [type: 271, value: FOO]
                  args:
                        [type: 267, value: a]
                  child:
                        [type: 267, value: a]
                        child:
                              [type: 300, value: +]
                              args:
                                    [type: 267, value: a]
      ...

Option -p is used for printing out the resulting AST. "example.ppl" is a binary file where AST is stored. If you wish to know how this file you can read this file and make some work with AST, please read INTERFACES section.

cppscan

This program create a token stream out of C file. The token stream can be piped to the cppscan or saved in a file using -o option.

Consider the following example:

% ./cppscan example.c
line # 1 directive[IF]
line # 1 special[DEFINED]
line # 1 SYMBOL[(]
line # 1 ident[A]
line # 1 SYMBOL[)]
line # 2 special[<macro_end>]
line # 2 directive[DEFINE]
line # 2 ident[FOO]
line # 2 SYMBOL[(]
line # 2 ident[a]
line # 2 SYMBOL[)]
line # 2 ident[a]
line # 2 SYMBOL[+]
line # 2 ident[a]
line # 3 special[]
...

As you can see the format is quite simple. "line # %num %name[%value]\n". This format should be changed for something more compact, but at the moment readability matters.

INSTALLATION

For successful cpplint installation you must have installed the follownig:

  • Flex
  • D parser

Download cpplint.tar.gz package.

% tar -xvf cpplint.tar.gz
% cd cpplint
% make
% PATH=$PATH:./

The last step is not obligatory if the directory with binaries cpplint, cppdast, cppscan would be in PATH.

AUTHORS

  • Artjoms Šinkarovs
Copyright © 2009 Artjoms Šinkarovs, $Date: 2009/05/05 22:33:34 $