4

I'm trying to modify/refactor input C source code. I'm trying to add a printf statement after every line of my input code.

For e.g. if my input is -

void foo(){
    // Sample input code
    int a = 0, b = 0;
    a++;
    if(a<5)
         b++;
    b--;
}

I would want to add the statement printf('Hi');, leading to -

void foo(){
    int a = 0, b = 0;
    printf('Hi');
    a++;
    printf('Hi');
    if(a<5){
         b++;
         printf('Hi');
    }
    printf('Hi');
    b--;
    printf('Hi');
}

As an initial step, I simply tried declaring a variable test and tried inserting it to the beginning of the AST generated by a random source code. Here's the python code that I was involved with, after having extracted the AST to the object ast -

for i in range(0,len(ast.ext)):
    ## Look for a function named 'foo'
    if(type(ast.ext[i]) == c_ast.FuncDef and ast.ext[i].decl.name == 'foo'):
        ## Store the list of AST node objects in functionBody
        functionBody    = ast.ext[i].body

        ## Create a Decl object for the variable test
        id_obj          = c_ast.ID('test')
        identifier_obj  = c_ast.IdentifierType(['int'])
        typedecl_obj    = c_ast.TypeDecl(id_obj.name,[],identifier_obj)
        decl_obj        = c_ast.Decl(id_obj.name,[],[],[],typedecl_obj,[],[])

        ## Append the object to a list.
        ## Concatenate to a copy of existing list of AST objects     
        lst1 = []
        lst1.append(decl_obj)
        lst2 = []
        lst2 = copy.deepcopy(functionBody.block_items)
        lst3 = []
        lst3 = lst1+lst2

        ## Create a modified AST and print content
        functionBody1 = c_ast.Compound(lst3)
        functionBody1.show()

I find no change in the resulting structure functionBody1 and also get the following error whenever I try to use its show( ) method.

'list' object has no attribute 'show'

Any idea as to where I'm going off track?

Thanks

Shash
  • 83
  • 7
  • Is there a reason that lst2 and lst3 are initialized to [] and then assigned something else? You don't do that to lst1. – Ira Baxter Jun 07 '12 at 19:43
  • @IraBaxter I have initialized _lst1_ to _[ ]_ as well. And there's no real reason for it. Just indicating that these variables are of type _list_. – Shash Jun 07 '12 at 20:12
  • Are you able to regenerate text for the unmodified function? – Ira Baxter Jun 09 '12 at 10:14

1 Answers1

2

I found three places where you were passing a list where you should have been passing None.

## Create a Decl object for the variable test
id_obj          = c_ast.ID('test')
identifier_obj  = c_ast.IdentifierType(['int'])
typedecl_obj    = c_ast.TypeDecl(id_obj.name,None,identifier_obj)
decl_obj        = c_ast.Decl(id_obj.name,[],[],[],typedecl_obj,None,None)

I am not really that familiar with this, as I am still learning pycparser too, but this change fixes your traceback for me.

ChipJust
  • 1,376
  • 12
  • 20
  • Thanks! That does the trick. How again did you figure this out? I really couldn't make that out from the available documentation. – Shash Jun 10 '12 at 19:20
  • 1
    I dug down into the class declarations in the pycparser code to see what it expected. The big clue I was pursuing was the error message, which was happening because when you do a show() it calls into each child to do a show(). So the error was indicating that you provided a list when what was expected was a object that supported a show() call. It took a while to figure out when parameters were not correct as there seems to be a real lack of examples for this code, apart from the examples included in the module itself. – ChipJust Jun 10 '12 at 20:24
  • No problem. I will probably start posting pycparser questions soon. Maybe you will answer mine...seems like not many people are doing things with this module anymore. – ChipJust Jun 11 '12 at 00:26
  • That's true Would love to assist :) – Shash Jun 11 '12 at 05:24