Hi Julia, I have a couple of new problems with coccinelle.
First, please have a look at the attached testc.c and test.cocci. Running test.cocci on testc.c results in a hang. The problems seems to be related to the number of (to-be-folded) labels. For the second problem, I attached pdev-simple.cocci. It is supposed to convert '&pdev->dev' dereferences to use a local variable. The rule (or, rather, a more complete version of it) works quite well, but it hangs on a couple of files (listed in the .cocci file). As usual I have no idea what might be wrong. Replacing <+... ...+> with <... ...> in the 'prb' rule resolves the hangup, but I have no idea why, and I don't know how to make it work for the generic case. I also tried a number of variants, which either did not work or also resulted in a hangup. I also attached the (almost) complete version of pdev.cocci. It is still work in progress, and a bit clumsy at times, but works quite well except for the hangups. Besides the hangup, the most challenging problem for me is how to count the number of instances of '&pdev->dev'. If you have an idea what might be wrong, please let me know. My version of spatch: spatch version 1.0.6-00053-g45ef175 compiled with OCaml version 4.02.3 Flags passed to the configure script: [none] Python scripting support: yes Syntax of regular expresssions: PCRE Thanks, Guenter
int f1(void); static int func(void *pdev) { int v1; int v2; int v3; int v4; int v5; int error; v1 = f1(); v3 = f1(); if (!v1 || !v3) { error = -1; goto l1; } v2 = f1(); if (v2) { error = v2; goto l2; } v5 = f1(); if (v5) { error = v5; goto l3; } v4 = f1(); if (v4) { error = v4; goto l4; } error = f1(); if (error) { goto l5; } error = f1(); if (error) { goto l5; } error = f1(); if (error) return error; error = f1(); if (error) { goto l6; } error = f1(); if (error) return error; error = f1(); if (error) { goto l7; } error = f1(); if (error) { goto l7; } error = f1(); if (error) { goto l8; } return 0; l8: l7: l6: l5: l4: l3: l2: l1: return error; }
virtual patch @unneeded_label@ identifier fn; position p1; identifier l1,l2; @@ fn(...) { <+... l1:@p1 l2: ...+> } @fold_label@ identifier unneeded_label.fn; identifier l,l1,l2; position p != unneeded_label.p1; position any p1; statement S; @@ fn(...) { <+... - goto l1; + goto l2; ... -l1: <... when != S l:@p1 ...> l2:@p ...+> }
virtual patch @initialize:python@ @@ f = open('coccinelle.log', 'a') @probe@ identifier p, probefn; declarer name module_platform_driver_probe; @@ ( module_platform_driver_probe(p, probefn); | struct platform_driver p = { .probe = probefn, }; | struct i2c_driver p = { .probe = probefn, }; | struct spi_driver p = { .probe = probefn, }; ) // Get type of device. // Using it ensures that we don't touch any other data structure // which might have a '->dev' object. @ptype depends on probe@ type T; identifier probe.probefn; identifier pdev; @@ probefn(T *pdev, ...) { ... } @e depends on probe@ identifier initfn; identifier d; identifier pdev; type ptype.T; position p; @@ initfn@p(T *pdev, ...) { ... struct device *d = &pdev->dev; ... } // Use existing 'struct device *' variable for transformations if available @prb@ identifier e.d; identifier initfn; identifier e.pdev; position e.p; type ptype.T; @@ initfn@p(T *pdev, ...) { ... struct device *d = &pdev->dev; <+... - &pdev->dev + d ...+> } // Otherwise make sure that a variable named 'dev' does not already exist. @script:python expected@ dev; @@ coccinelle.dev = 'dev' @have_dev depends on probe@ identifier initfn; identifier expected.dev; identifier pdev; type ptype.T; position p; @@ initfn@p(T *pdev, ...) { ... when any dev ... } // Idea is to only replace &pdev->dev if it is used at least twice // and if no variable with the same name exists. The rule below doesn't // seem to work, though. // Q: How do we determine that &pdev->dev exists at least twice ? /* @count depends on !prb@ identifier initfn != { prb.initfn, have_dev.initfn }; identifier pdev; type ptype.T; position p; @@ initfn@p(T *pdev, ...) { ... &pdev->dev <+... &pdev->dev ...+> } */ // The following rule hangs on: // drivers/input/keyboard/adp5588-keys.c // drivers/input/keyboard/adp5589-keys.c // drivers/input/touchscreen/wdt87xx_i2c.c // transform ... @new depends on probe && !have_dev && !e@ identifier initfn; identifier pdev; type ptype.T; position p; @@ initfn@p(T *pdev, ...) { <+... - &pdev->dev + dev ...+> } // ... and introduce new variable if needed @newdecl depends on new@ identifier new.initfn; identifier pdev; type ptype.T; position p; @@ initfn@p(T *pdev, ...) { + struct device *dev = &pdev->dev; ... } @script:python depends on prb@ p << e.p; @@ print >> f, "%s:pdev1:%s" % (p[0].file, p[0].line) @script:python@ p << newdecl.p; @@ print >> f, "%s:pdev2:%s" % (p[0].file, p[0].line)
virtual patch @initialize:python@ @@ f = open('coccinelle.log', 'a') @probe@ identifier p, probefn; declarer name module_platform_driver_probe; @@ ( module_platform_driver_probe(p, probefn); | struct platform_driver p = { .probe = probefn, }; | struct i2c_driver p = { .probe = probefn, }; | struct spi_driver p = { .probe = probefn, }; ) // Get type of device. // Using it ensures that we don't touch any other data structure // which might have a '->dev' object. @ptype depends on probe@ type T; identifier probe.probefn; identifier pdev; @@ probefn(T *pdev, ...) { ... } // The following rule hangs on: // drivers/input/keyboard/adp5588-keys.c // drivers/input/keyboard/adp5589-keys.c // drivers/input/touchscreen/wdt87xx_i2c.c @prb depends on probe@ identifier probe.probefn; identifier pdev; type ptype.T; position p; @@ probefn@p(T *pdev, ...) { + struct device *dev = &pdev->dev; <+... - &pdev->dev + dev ...+> }
_______________________________________________ Cocci mailing list Cocci@systeme.lip6.fr https://systeme.lip6.fr/mailman/listinfo/cocci