views:

79

answers:

1

I require a java code for converting a C program into a control flow graph.

Can any one please help me out with it?

A: 

July 12th is going to be a tough deadline to meet, but you can do it.

Here is the general strategy that I would use if I were completing this project myself:

  1. Preprocess the input C file (also called the translation unit). This generates the preprocessed translation unit.
  2. Parse the preprocessed translation unit as an abstract syntax tree (AST).
  3. Traverse the AST, creating a graph node n for each function declaration. Add (function name, n) to a map.
  4. Traverse the AST, building a graph of the control flow. Consider how you are going to represent the following, special cases in the control flow graph:
    • Labelled statements
    • if/else
    • if not followed by else.
    • goto
    • switch
    • Fall-through cases and break within switch.
    • Loops such as do...while, while, and for.
    • break within a loop
    • continue within a loop
    • return
    • Regular function calls
    • Calling the target of a function pointer
    • End of a void function definition (no return)
    • End of int main() and int main(int, char**), which does not require return
    • exit
    • Intermediate values
  5. Output the graph in DOT format.

You may want to use this test program, which I think has all of the "special" cases:

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

void usage(const char *arg0)
{
    fprintf(stderr, "Usage: %s [INTEGER]\n", arg0);
    fprintf(stderr, "Dummy program\n");
    exit(EXIT_FAILURE);
}

int g_a;

void init()
{
    g_a = 3;
}

int return_4()
{
    return 4;
}

void uninit()
{
}

int main(int argc, char **argv)
{
    if (argc <= 1) {
        usage(argv[0]);
    }

    if (argc > 2) {
        printf("You only need to pass one argument.\n");
    }
    else {
        init();
    }

    const int i = atoi(argv[1]);
    int j;
before_switch: j = 0;
switch_i: switch (i) {
        case 3:
            for(; j < 3; ++j)
                printf(".");
        case 17:
            for(; j < 17; ++j)
                printf(".");
            if (i == 3 || i == 17)
                printf("\n");
        case -4:
            printf("You picked one of my favorite numbers (17, 3, and -4)!\n");
            break;

        case -1:
            printf("Cleaning up\n");
            goto cleanup;

        default:
            printf("I don't like that number.\n");
    }

    j = 0;
do_loop_1: do {
        if (j++ % 2 == 0)
            continue;
        if (j == 10)
            break;

        printf("j is %d.\n", j);
    } while(j < 30);

    j = 10;
    while (j > 0) {
        if (4 == return_4())
            break;
        --j;
    }

    void (*voidFn)() = &uninit;
    voidFn();
    init();

cleanup:
    uninit();
    return EXIT_SUCCESS;
}

I would also use the following open source libraries:

  1. JCPP, a pure Java implementation of the C preprocessor, for preprocessing the translation unit
  2. ANTLR for parsing along with the ANTLR C grammar
  3. Grappa for the graph data structures and graph drawing (if required)
Daniel Trebbien
Your example doesn't cover the nasty things you can write in C. It is perfectly legal to put a label in the middle of a block, and **goto** it from outside the block. It is perfectly legal to put a build switch statments whose cases are not well structured. In Gcc, you have goto indirect. Most versions of C allow setjmp. All of these can make what appear to be structured program into a spaghetti tangle.
Ira Baxter
@Ira: True. I had forgotten about these features of C. Hopefully, though, following this strategy will yield a program that *could* handle these additional cases.
Daniel Trebbien