Im trying to use spatch in the Perl codebase
git://perl5.git.perl.org/perl.git
to convert a struct->field ref to a macro, and am encountering difficulties.

I think theyre due to Perl's heavy use of macros, but Ive had a few
surprises,
which leaves me uncertain of my understanding.

My cocci file is pretty simple, but misses stuff.
It finds 1 change in toke.c, but misses everything in op.c,
which is where the bulk of the field-refs happen.

jimc@chumly:~/projects/perl-core/perl$ spatch -sp_file ../op_sibl.cocci
-verbose_parsing -debug -show_cocci -all_includes toke.c
init_defs_builtins: /usr/share/coccinelle/standard.h
-----------------------------------------------------------------------
processing semantic patch file: ../op_sibl.cocci
with isos from: /usr/share/coccinelle/standard.iso
-----------------------------------------------------------------------


@ sibling_LHS@
expression OP;
expression OP2;
@@

- OP->op_sibling = OP2
+ setOpSibling(OP, OP2)

@sibling_RHS@
expression OP;
@@

- OP->op_sibling
+ OpSibling(OP)

@@
type TOP;
@@

- TOP->op_sibling
+ OpSibling(TOP)


189 191
Fatal error: exception Failure("minus: parse error:
 = File "../op_sibl.cocci", line 22, column 5,  charpos = 189
     around = '->', whole content = - TOP->op_sibling
")


I added the TOP rule in attempt to catch simple vars, but given the error I
pulled it out.
Once I yanked it, it found 1 transformation:

HANDLING: toke.c
diff =
--- toke.c 2011-03-02 09:09:57.392038433 -0500
+++ /tmp/cocci-output-31503-f60bf3-toke.c 2011-03-02 13:02:00.717080475
-0500
@@ -2370,7 +2370,7 @@ S_sublex_start(pTHX)
     }
     else if (op_type == OP_BACKTICK && PL_lex_op) {
  /* readpipe() vas overriden */
- cSVOPx(cLISTOPx(cUNOPx(PL_lex_op)->op_first)->op_first->op_sibling)->op_sv
= tokeq(PL_lex_stuff);
+ cSVOPx(OpSibling(cLISTOPx(cUNOPx(PL_lex_op)->op_first)->op_first))->op_sv
= tokeq(PL_lex_stuff);
  pl_yylval.opval = PL_lex_op;
  PL_lex_op = NULL;
  PL_lex_stuff = NULL;
Note: processing took   113.1s: toke.c

the patch clearly finds and changes a single expression, but :

- it doesnt see it as the LHS of an assignment, why not ?
I gather order is not a good way to construct cocci rules, but Im unclear
on
how to spec that dependence.  OP's type here is a typedef, ie one of:
perl.h:typedef struct op OP;
perl.h:typedef struct cop COP;
perl.h:typedef struct unop UNOP;
perl.h:typedef struct binop BINOP;
perl.h:typedef struct listop LISTOP;
perl.h:typedef struct logop LOGOP;
where .+OPs have OP fields in common, but are not *inherited* (ie strictly
C)
All these perl ideosyncracies leave me puzzled on how to apply SmPL to them.

- would a proper binding rule also help to reduce processing time ?

- it does see and transform a complex expression.
The latter is the reason I tried the TOP rule above, thinking that perhaps
expression was only
expression (not a simple term)  This doesnt seem to be the case, and wasnt
what I expected apriori - Im just saying it all here in case Ive missed some
other aspect.


So, on to the macro-ish problems...
parsing toke.c is much more successful than op.c, so I start there.

maybe 10 most problematic tokens
-----------------------------------------------------------------------
pTHX_: present in 80 parsing errors
example:

       void
       Perl_munge_qwlist_to_paren_list(pTHX_ OP *qwlist)
       {
s: present in 51 parsing errors
example:

       char *
       Perl_scan_vstring(pTHX_ const char *s, const char *const e, SV *sv)
       {


I suspect that both these problems, and many others, are due to the defn of
pTHX_
which is a set of layered macros that introduce a maybe-term,
either blank-whitespace, or a "type var," as 1st item in a function
parameter-list,
(Read the trailing _ as a comma when the expansion isnt empty)
Ive pasted in some of the macros for perusal, skip if obvious/uninteresting.

#ifdef PERL_IMPLICIT_CONTEXT
#  define tTHX  PerlInterpreter*
#  define pTHX  register tTHX my_perl PERL_UNUSED_DECL
#  define aTHX  my_perl
#  ifdef PERL_GLOBAL_STRUCT
#    define dTHXa(a)    dVAR; pTHX = (tTHX)a
#  else
#    define dTHXa(a)    pTHX = (tTHX)a
#  endif
#  ifdef PERL_GLOBAL_STRUCT
#    define dTHX                dVAR; pTHX = PERL_GET_THX
#  else
#    define dTHX                pTHX = PERL_GET_THX
#  endif
#  define pTHX_         pTHX,
#  define aTHX_         aTHX,

#ifndef pTHX
/* Don't bother defining tTHX and sTHX; using them outside
 * code guarded by PERL_IMPLICIT_CONTEXT is an error.
 */
#  define pTHX          void
#  define pTHX_

building perl for threads indirectly turns on PERL_IMPLICIT_CONTEXT,
which plugs the interpreter pointer into the 1st argument of *many* api
functions.



Parsing op.c shows many BAD lines:

jimc@chumly:~/projects/perl-core/build-threads$ grep BAD ../spatch-res-op
|wc
    189    1088    9487

jimc@chumly:~/projects/perl-core/build-threads$ grep BAD ../spatch-res-op
BAD:!!!!! #define CALL_OPFREEHOOK(o) if (PL_opfreehook) PL_opfreehook(aTHX_
o)
BAD:!!!!! Perl_Slab_Alloc(pTHX_ size_t sz)
BAD:!!!!!     I32 **const slabs = PL_slabs;
BAD:!!!!! S_Slab_to_rw(pTHX_ void *op)
BAD:!!!!! Perl_op_refcnt_inc(pTHX_ OP *o)
BAD:!!!!! Perl_op_refcnt_dec(pTHX_ OP *o)
BAD:!!!!! Perl_Slab_Free(pTHX_ void *op)
BAD:!!!!!      : PL_check[type](aTHX_ (OP*)o))
BAD:!!!!!     STMT_START { \

many of these appear to be the pTHX, as mentioned above,
CALL_OPFREEHOOK may also be problematic:
which expands to:
    if ((my_perl->Iopfreehook)) (my_perl->Iopfreehook)(my_perl, o);

What exactly does BAD !!! mean anyway ?
Is it more or less as described in /usr/share/coccinelle/standard.h ?
or is it that the dynamic expansion is insufficient ?


Overall, whats the right strategy for a project to help coccinelle to
support it ?
- a project specific  -macro_file           <file>
Do you keep links to such project files that would help in understanding
whats needed ?


lastly, though these are rather unimportant ...

jimc@chumly:~/projects/perl-core/perl$ spatch -sp_file ../op_sibl.cocci
-verbose_parsing -debug -show_cocci -all_includes -parse_ch op.c 2>
../spatch-res-op
NB total files = 1; perfect = 0; pbs = 1; timeout = 0; =========> 0%
nb good = 296,  nb passed = 70 =========> 23.648649% passed
nb good = 296,  nb bad = 9862 =========> 2.913959% good
jimc@chumly:~/projects/perl-core/perl$ wc ../spatch-res-op
 10790  46067 333773 ../spatch-res-op

what is NB and nb ?   Noto Bono or Number of Blocks ?
what does passed mean ?
why does nb good show up 2x ?
%good = nb-good / (nb-bad + nb-good)
_______________________________________________
Cocci mailing list
[email protected]
http://lists.diku.dk/mailman/listinfo/cocci
(Web access from inside DIKUs LAN only)

Reply via email to