0

I need to write a Python program that parses C source code files and adds a hidden parameter at the end of each function declaration.

More precisely, I need to change something like this:

void f(int a, int b, int c) { ... }

into something like this:

void f(int a, int b, int c, int hiddenArg) { ... }

Obviously, I am going to need to edit all the calls to this function from other functions, too.

I need to do this using pycparser, but I can not figure out the proper way to edit an AST once I have read it. Is there a proper way to do this that I am missing (or any way whatsoever)?

Zehanort
  • 458
  • 2
  • 10
  • "each" function declaration? Won't that break a lot of functions that need specific type signatures, such as `main`? – Joseph Sible-Reinstate Monica Jan 06 '20 at 00:00
  • @JosephSible-ReinstateMonica I want to do this only to helper functions in OpenCL kernel files (*.cl). Nothing will break, this is guaranteed for other reasons in my case. – Zehanort Jan 06 '20 at 00:03
  • Not clear, just declaration not the implementation or the calls should be updated ? – Ôrel Jan 06 '20 at 00:05
  • @Ôrel I will need to change the calls eventually as I have noted, but this is not the main concern right now. I just need to know if there is a proper way to edit the AST nodes constructed by `pycparser`. – Zehanort Jan 06 '20 at 00:06
  • Perhaps you can override `visit_FuncCall` if you do always the same extra arg – Ôrel Jan 06 '20 at 00:12
  • That is what I am trying to do right now, but I can not make it work... I need to create a new `visit_FuncCall` that calls the old one, after changing the name of the called function. Do you have any suggestions? – Zehanort Jan 06 '20 at 01:55

1 Answers1

0

As an example of modifying the AST, here's changing the function declarations to have a new parameter:

class ParamAdder(c_ast.NodeVisitor):
    def visit_FuncDecl(self, node):
        ty = c_ast.TypeDecl(declname='_hidden',
                            quals=[],
                            type=c_ast.IdentifierType(['int']))
        newdecl = c_ast.Decl(
                    name='_hidden',
                    quals=[],
                    storage=[],
                    funcspec=[],
                    type=ty,
                    init=None,
                    bitsize=None,
                    coord=node.coord)
        if node.args:
            node.args.params.append(newdecl)
        else:
            node.args = c_ast.ParamList(params=[newdecl])

This changes all functions. Obviously, you can add a condition in the visitor to change only certain functions that you're interested in.

You'd modify calls to this function in a similar manner using a visit_FuncCall.

Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412