All of lore.kernel.org
 help / color / mirror / Atom feed
* [cocci] Can you match identifiers of a specific type?
@ 2022-02-28  4:24 Eric Wheeler
  2022-02-28  6:08 ` Julia Lawall
  0 siblings, 1 reply; 8+ messages in thread
From: Eric Wheeler @ 2022-02-28  4:24 UTC (permalink / raw)
  To: cocci

Hello,

Can I match only specific identifier types and names where the type is a 
typedef? I've been reading as much as I can about Coccinelle but I've not 
found a way to do it. 

I'm trying to move global calculation structures into its own typedef 
structure to create a thread-safe environment where multiple threads can 
work on different struct instances.  Right now the code works only on 
static global values so parallelism is not possible without fork()ing.  
(This is for the www.xnec2c.org project.)

The code that looks pretty close to the following:

	// Globals
	typedef struct {
		int a;
	} data_t

	data_t data;

	void f(char *data)
	{
		data[0] = 0; // parameter
	}

	void g()
	{
		data.a = 0; // global
	}

I want to put all of the global 'data' variables of type 'data_t' into a 
new structure as follows:

	typedef struct {
		data_t data;
		// and many others...
	} nec_t;

	nec_t *nec;

and replace the functions above as:

	void f(char *data)
	{
		data[0] = 0; // Does NOT change
	}

	void g()
	{
		nec->data.a = 0; // This DOES change
	}

With a rule something like this:

	@ rule1 @
	typedef data_t;
	type T = {data_t};
	identifier I = {data};
	@@
	-I
	+nec->I

But of course T isn't actually used in that cocci example, but I want to 
make sure that I is always of type T but I'm not sure how. I tried 
idexpression but either it is not intended for this purpose. This gives a 
cocci syntax error, so clearly I do not have it correct, but maybe it 
explains what I'm trying to do:

	@ rule1 @
	typedef data_t;
	type T = {data_t};
	idexpression T I = {data};
	@@
	-I
	+nec->I

The whole struct I'm trying to refactor is below, you'll notice there are 
lots of different typedefs that are all being moved into the nec_t 
structure, but hopefully the description above explains what I'm trying to 
do.  The global variable names like "data" are always named the same, 
hence "identifier I={data}".  I just want to make sure that the 
replacement enforces the following:
   1. "data" is a global variable and it is named "data"
   2. "data" is of type "data_t"

The xnec2c code I am refactoring is very sensitive to the difference 
between a "complex double" and a "double" since complex numbers and real 
numbers can be multipled in C without error or compiler warnings.  

There are type collisions between local and global variables (I know, bad 
form, but thats how it is) so I need to make sure only the same data types 
are replaced even if the names collide between local/global identififers.

If the wrong local variable of type "double" was replaced with a global 
variable of type "complex double" or vice-versa, then the calculations 
would be wrong and it would be very difficult (or impossible) to figure 
out why.

Most of the identifiers like "near_field" are pretty unique and could be a 
simple search-replace with nec->near_field, but others like "data", "cm", 
and "cmag" might be used with different types so I hope Coccinelle can 
enforce replacement of the variable type.

Thanks for your help!

-Eric

More detail if you're curious:

The actual new nec_t structure looks like this; all of these fields are new and the code needs to replace
all occurances of each field with nec->field:

	typedef struct
	{
		// rad_pattern_t *rad_pattern; // pointer to the index into rad_pattern[freq_step]

		// Near E/H field data
		near_field_t near_field;

		complex double *cm;

		// Needed data
		impedance_data_t impedance_data;

		// Data for various calculations
		calc_data_t calc_data;

		// Magnitude of seg/patch current/charge
		double *cmag, *ct1m, *ct2m;

		crnt_t crnt;

		dataj_t dataj;

		data_t data;

		fpat_t fpat;

		ggrid_t ggrid;

		gnd_t gnd;

		gwav_t gwav;

		incom_t incom;

		matpar_t matpar;

		netcx_t netcx;

		save_t save;

		segj_t segj;

		smat_t smat;

		vsorc_t vsorc;

		zload_t zload;
	} nec_t;


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [cocci] Can you match identifiers of a specific type?
  2022-02-28  4:24 [cocci] Can you match identifiers of a specific type? Eric Wheeler
@ 2022-02-28  6:08 ` Julia Lawall
  2022-03-01  1:28   ` Eric Wheeler
  0 siblings, 1 reply; 8+ messages in thread
From: Julia Lawall @ 2022-02-28  6:08 UTC (permalink / raw)
  To: Eric Wheeler; +Cc: cocci



On Sun, 27 Feb 2022, Eric Wheeler wrote:

> Hello,
>
> Can I match only specific identifier types and names where the type is a
> typedef? I've been reading as much as I can about Coccinelle but I've not
> found a way to do it.
>
> I'm trying to move global calculation structures into its own typedef
> structure to create a thread-safe environment where multiple threads can
> work on different struct instances.  Right now the code works only on
> static global values so parallelism is not possible without fork()ing.
> (This is for the www.xnec2c.org project.)
>
> The code that looks pretty close to the following:
>
> 	// Globals
> 	typedef struct {
> 		int a;
> 	} data_t
>
> 	data_t data;
>
> 	void f(char *data)
> 	{
> 		data[0] = 0; // parameter
> 	}
>
> 	void g()
> 	{
> 		data.a = 0; // global
> 	}
>
> I want to put all of the global 'data' variables of type 'data_t' into a
> new structure as follows:
>
> 	typedef struct {
> 		data_t data;
> 		// and many others...
> 	} nec_t;
>
> 	nec_t *nec;
>
> and replace the functions above as:
>
> 	void f(char *data)
> 	{
> 		data[0] = 0; // Does NOT change
> 	}
>
> 	void g()
> 	{
> 		nec->data.a = 0; // This DOES change
> 	}
>
> With a rule something like this:
>
> 	@ rule1 @
> 	typedef data_t;
> 	type T = {data_t};
> 	identifier I = {data};

This means that your variable I should always be called "data".  Is that
what you intended?

You should be able to do

idexpression data_t I = {data};

Then you want to use the name in a structure field.  Te problem is that a
structure field is not an expression, it is an identifier.  So you have to
make the match in two ways:

@@
idexpression data_t I = {data};
identifier j;
@@

-I@j
+nec->j

julia


> 	@@
> 	-I
> 	+nec->I
>
> But of course T isn't actually used in that cocci example, but I want to
> make sure that I is always of type T but I'm not sure how. I tried
> idexpression but either it is not intended for this purpose. This gives a
> cocci syntax error, so clearly I do not have it correct, but maybe it
> explains what I'm trying to do:
>
> 	@ rule1 @
> 	typedef data_t;
> 	type T = {data_t};
> 	idexpression T I = {data};
> 	@@
> 	-I
> 	+nec->I
>
> The whole struct I'm trying to refactor is below, you'll notice there are
> lots of different typedefs that are all being moved into the nec_t
> structure, but hopefully the description above explains what I'm trying to
> do.  The global variable names like "data" are always named the same,
> hence "identifier I={data}".  I just want to make sure that the
> replacement enforces the following:
>    1. "data" is a global variable and it is named "data"
>    2. "data" is of type "data_t"
>
> The xnec2c code I am refactoring is very sensitive to the difference
> between a "complex double" and a "double" since complex numbers and real
> numbers can be multipled in C without error or compiler warnings.
>
> There are type collisions between local and global variables (I know, bad
> form, but thats how it is) so I need to make sure only the same data types
> are replaced even if the names collide between local/global identififers.
>
> If the wrong local variable of type "double" was replaced with a global
> variable of type "complex double" or vice-versa, then the calculations
> would be wrong and it would be very difficult (or impossible) to figure
> out why.
>
> Most of the identifiers like "near_field" are pretty unique and could be a
> simple search-replace with nec->near_field, but others like "data", "cm",
> and "cmag" might be used with different types so I hope Coccinelle can
> enforce replacement of the variable type.
>
> Thanks for your help!
>
> -Eric
>
> More detail if you're curious:
>
> The actual new nec_t structure looks like this; all of these fields are new and the code needs to replace
> all occurances of each field with nec->field:
>
> 	typedef struct
> 	{
> 		// rad_pattern_t *rad_pattern; // pointer to the index into rad_pattern[freq_step]
>
> 		// Near E/H field data
> 		near_field_t near_field;
>
> 		complex double *cm;
>
> 		// Needed data
> 		impedance_data_t impedance_data;
>
> 		// Data for various calculations
> 		calc_data_t calc_data;
>
> 		// Magnitude of seg/patch current/charge
> 		double *cmag, *ct1m, *ct2m;
>
> 		crnt_t crnt;
>
> 		dataj_t dataj;
>
> 		data_t data;
>
> 		fpat_t fpat;
>
> 		ggrid_t ggrid;
>
> 		gnd_t gnd;
>
> 		gwav_t gwav;
>
> 		incom_t incom;
>
> 		matpar_t matpar;
>
> 		netcx_t netcx;
>
> 		save_t save;
>
> 		segj_t segj;
>
> 		smat_t smat;
>
> 		vsorc_t vsorc;
>
> 		zload_t zload;
> 	} nec_t;
>
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [cocci] Can you match identifiers of a specific type?
  2022-02-28  6:08 ` Julia Lawall
@ 2022-03-01  1:28   ` Eric Wheeler
  2022-03-01  2:01     ` Eric Wheeler
  2022-03-01  6:09     ` Julia Lawall
  0 siblings, 2 replies; 8+ messages in thread
From: Eric Wheeler @ 2022-03-01  1:28 UTC (permalink / raw)
  To: Julia Lawall; +Cc: cocci

On Mon, 28 Feb 2022, Julia Lawall wrote:
> On Sun, 27 Feb 2022, Eric Wheeler wrote:
> 
> > Hello,
> >
> > Can I match only specific identifier types and names where the type is a
> > typedef? I've been reading as much as I can about Coccinelle but I've not
> > found a way to do it.
> >
> > I'm trying to move global calculation structures into its own typedef
> > structure to create a thread-safe environment where multiple threads can
> > work on different struct instances.  Right now the code works only on
> > static global values so parallelism is not possible without fork()ing.
> > (This is for the www.xnec2c.org project.)
> >
> > The code that looks pretty close to the following:
> >
> > 	// Globals
> > 	typedef struct {
> > 		int a;
> > 	} data_t
> >
> > 	data_t data;
> >
> > 	void f(char *data)
> > 	{
> > 		data[0] = 0; // parameter
> > 	}
> >
> > 	void g()
> > 	{
> > 		data.a = 0; // global
> > 	}
> >
> > I want to put all of the global 'data' variables of type 'data_t' into a
> > new structure as follows:
> >
> > 	typedef struct {
> > 		data_t data;
> > 		// and many others...
> > 	} nec_t;
> >
> > 	nec_t *nec;
> >
> > and replace the functions above as:
> >
> > 	void f(char *data)
> > 	{
> > 		data[0] = 0; // Does NOT change
> > 	}
> >
> > 	void g()
> > 	{
> > 		nec->data.a = 0; // This DOES change
> > 	}
> >
> > With a rule something like this:
> >
> > 	@ rule1 @
> > 	typedef data_t;
> > 	type T = {data_t};
> > 	identifier I = {data};
> 
> This means that your variable I should always be called "data".  Is that
> what you intended?
> 
> You should be able to do
> 
> idexpression data_t I = {data};
> 
> Then you want to use the name in a structure field.  Te problem is that a
> structure field is not an expression, it is an identifier.  So you have to
> make the match in two ways:
> 
> @@
> idexpression data_t I = {data};
> identifier j;
> @@
> 
> -I@j
> +nec->j

Thanks Julia, that seems to work (I added `typedef data_t;` to the .cocci 
file).

What does I@j mean?  Can you point me at documentation?

-Eric

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [cocci] Can you match identifiers of a specific type?
  2022-03-01  1:28   ` Eric Wheeler
@ 2022-03-01  2:01     ` Eric Wheeler
  2022-03-01  6:13       ` Julia Lawall
  2022-03-01  6:09     ` Julia Lawall
  1 sibling, 1 reply; 8+ messages in thread
From: Eric Wheeler @ 2022-03-01  2:01 UTC (permalink / raw)
  To: Julia Lawall; +Cc: cocci

On Mon, 28 Feb 2022, Eric Wheeler wrote:
> On Mon, 28 Feb 2022, Julia Lawall wrote:
> > On Sun, 27 Feb 2022, Eric Wheeler wrote:
> > 
> > > Hello,
> > >
> > > Can I match only specific identifier types and names where the type is a
> > > typedef? I've been reading as much as I can about Coccinelle but I've not
> > > found a way to do it.
> > >
> > > I'm trying to move global calculation structures into its own typedef
> > > structure to create a thread-safe environment where multiple threads can
> > > work on different struct instances.  Right now the code works only on
> > > static global values so parallelism is not possible without fork()ing.
> > > (This is for the www.xnec2c.org project.)
> > >
> > > The code that looks pretty close to the following:
> > >
> > > 	// Globals
> > > 	typedef struct {
> > > 		int a;
> > > 	} data_t
> > >
> > > 	data_t data;
> > >
> > > 	void f(char *data)
> > > 	{
> > > 		data[0] = 0; // parameter
> > > 	}
> > >
> > > 	void g()
> > > 	{
> > > 		data.a = 0; // global
> > > 	}
> > >
> > > I want to put all of the global 'data' variables of type 'data_t' into a
> > > new structure as follows:
> > >
> > > 	typedef struct {
> > > 		data_t data;
> > > 		// and many others...
> > > 	} nec_t;
> > >
> > > 	nec_t *nec;
> > >
> > > and replace the functions above as:
> > >
> > > 	void f(char *data)
> > > 	{
> > > 		data[0] = 0; // Does NOT change
> > > 	}
> > >
> > > 	void g()
> > > 	{
> > > 		nec->data.a = 0; // This DOES change
> > > 	}
> > >
> > > With a rule something like this:
> > >
> > > 	@ rule1 @
> > > 	typedef data_t;
> > > 	type T = {data_t};
> > > 	identifier I = {data};
> > 
> > This means that your variable I should always be called "data".  Is that
> > what you intended?
> > 
> > You should be able to do
> > 
> > idexpression data_t I = {data};
> > 
> > Then you want to use the name in a structure field.  Te problem is that a
> > structure field is not an expression, it is an identifier.  So you have to
> > make the match in two ways:
> > 
> > @@
> > idexpression data_t I = {data};
> > identifier j;
> > @@
> > 
> > -I@j
> > +nec->j
> 
> Thanks Julia, that seems to work (I added `typedef data_t;` to the .cocci 
> file).
> 


Ok so this worked in the simple example .c file:
	@ rule1 @
	typedef data_t;
	global idexpression data_t I = {data};
	identifier j;
	@@
	-I@j
	+nec->j

But when I try it on the actual code base I get this:
	]# spatch --sp-file nec-refactor2.cocci src/xnec2c.c
	init_defs_builtins: /usr/local/coccinelle-git/bin/lib/coccinelle/standard.h
	(ONCE) Expected tokens data_t
	Skipping: src/xnec2c.c

I have tried:
  * adding `-I src/`
  * adding `--include src/common.h --include src/shared.h` where data_t is defined.
  * adding --include-headers-for-types
  * adding --recursive-includes
  * Removing the `global` specifier on the idexpression.

None of these seem to work, they all skip with the "(ONCE) Expected tokens data_t" error.

However, if I hack "data_t data;" into the top of xnec2c.c then it works.

There seems to be a problem finding the `data_t data` definition through the headers.  

What should I do?  Here is the .c file if you want to take a look:
	https://github.com/KJ7LNW/xnec2c/blob/master/src/xnec2c.c

and the .h file with data_t:
	https://github.com/KJ7LNW/xnec2c/blob/master/src/shared.h#L219

Here is the version:

]# spatch --version
spatch version 1.1.1-00044-gb2a4b9b compiled with OCaml version 4.05.0
Flags passed to the configure script: --prefix=/usr/local/coccinelle-git
OCaml scripting support: yes
Python scripting support: yes
Syntax of regular expressions: PCRE

> What does I@j mean?  Can you point me at documentation?

-Eric

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [cocci] Can you match identifiers of a specific type?
  2022-03-01  1:28   ` Eric Wheeler
  2022-03-01  2:01     ` Eric Wheeler
@ 2022-03-01  6:09     ` Julia Lawall
  1 sibling, 0 replies; 8+ messages in thread
From: Julia Lawall @ 2022-03-01  6:09 UTC (permalink / raw)
  To: Eric Wheeler; +Cc: cocci



On Mon, 28 Feb 2022, Eric Wheeler wrote:

> On Mon, 28 Feb 2022, Julia Lawall wrote:
> > On Sun, 27 Feb 2022, Eric Wheeler wrote:
> >
> > > Hello,
> > >
> > > Can I match only specific identifier types and names where the type is a
> > > typedef? I've been reading as much as I can about Coccinelle but I've not
> > > found a way to do it.
> > >
> > > I'm trying to move global calculation structures into its own typedef
> > > structure to create a thread-safe environment where multiple threads can
> > > work on different struct instances.  Right now the code works only on
> > > static global values so parallelism is not possible without fork()ing.
> > > (This is for the www.xnec2c.org project.)
> > >
> > > The code that looks pretty close to the following:
> > >
> > > 	// Globals
> > > 	typedef struct {
> > > 		int a;
> > > 	} data_t
> > >
> > > 	data_t data;
> > >
> > > 	void f(char *data)
> > > 	{
> > > 		data[0] = 0; // parameter
> > > 	}
> > >
> > > 	void g()
> > > 	{
> > > 		data.a = 0; // global
> > > 	}
> > >
> > > I want to put all of the global 'data' variables of type 'data_t' into a
> > > new structure as follows:
> > >
> > > 	typedef struct {
> > > 		data_t data;
> > > 		// and many others...
> > > 	} nec_t;
> > >
> > > 	nec_t *nec;
> > >
> > > and replace the functions above as:
> > >
> > > 	void f(char *data)
> > > 	{
> > > 		data[0] = 0; // Does NOT change
> > > 	}
> > >
> > > 	void g()
> > > 	{
> > > 		nec->data.a = 0; // This DOES change
> > > 	}
> > >
> > > With a rule something like this:
> > >
> > > 	@ rule1 @
> > > 	typedef data_t;
> > > 	type T = {data_t};
> > > 	identifier I = {data};
> >
> > This means that your variable I should always be called "data".  Is that
> > what you intended?
> >
> > You should be able to do
> >
> > idexpression data_t I = {data};
> >
> > Then you want to use the name in a structure field.  Te problem is that a
> > structure field is not an expression, it is an identifier.  So you have to
> > make the match in two ways:
> >
> > @@
> > idexpression data_t I = {data};
> > identifier j;
> > @@
> >
> > -I@j
> > +nec->j
>
> Thanks Julia, that seems to work (I added `typedef data_t;` to the .cocci
> file).
>
> What does I@j mean?  Can you point me at documentation?

Match a thing according to both I and j.  It's like for position
variables.  One may write e@p to both match the expression e and get its
position.

This is discussed on page 6 in the documentation that is on the Coccinelle
web page:

https://coccinelle.gitlabpages.inria.fr/website/docs/main_grammar.pdf

A position metavariable is used by attaching it using @ to any token,
including another metavariable. Its value is the position (file, line
number, etc.) of the code matched by the token. It is also possible to
attach expression, declaration, type, initialiser, and statement
metavariables in this manner. In that case, the metavariable is bound to
the closest enclosing expression, declaration, etc. If such a metavariable
is itself followed by a position metavariable, the position metavariable
applies to the metavariable that it follows, and not to the attached
token. This makes it possible to get eg the starting and ending position
of f(...), by writing f(...)@E@p, for expression metavariable E and
position metavariable p. This attachment notation for metavariables of
type other than position can also be expressed with a conjunction, but the
@ notation may be more concise.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [cocci] Can you match identifiers of a specific type?
  2022-03-01  2:01     ` Eric Wheeler
@ 2022-03-01  6:13       ` Julia Lawall
  2022-03-02  2:55         ` Eric Wheeler
  0 siblings, 1 reply; 8+ messages in thread
From: Julia Lawall @ 2022-03-01  6:13 UTC (permalink / raw)
  To: Eric Wheeler; +Cc: cocci



On Mon, 28 Feb 2022, Eric Wheeler wrote:

> On Mon, 28 Feb 2022, Eric Wheeler wrote:
> > On Mon, 28 Feb 2022, Julia Lawall wrote:
> > > On Sun, 27 Feb 2022, Eric Wheeler wrote:
> > >
> > > > Hello,
> > > >
> > > > Can I match only specific identifier types and names where the type is a
> > > > typedef? I've been reading as much as I can about Coccinelle but I've not
> > > > found a way to do it.
> > > >
> > > > I'm trying to move global calculation structures into its own typedef
> > > > structure to create a thread-safe environment where multiple threads can
> > > > work on different struct instances.  Right now the code works only on
> > > > static global values so parallelism is not possible without fork()ing.
> > > > (This is for the www.xnec2c.org project.)
> > > >
> > > > The code that looks pretty close to the following:
> > > >
> > > > 	// Globals
> > > > 	typedef struct {
> > > > 		int a;
> > > > 	} data_t
> > > >
> > > > 	data_t data;
> > > >
> > > > 	void f(char *data)
> > > > 	{
> > > > 		data[0] = 0; // parameter
> > > > 	}
> > > >
> > > > 	void g()
> > > > 	{
> > > > 		data.a = 0; // global
> > > > 	}
> > > >
> > > > I want to put all of the global 'data' variables of type 'data_t' into a
> > > > new structure as follows:
> > > >
> > > > 	typedef struct {
> > > > 		data_t data;
> > > > 		// and many others...
> > > > 	} nec_t;
> > > >
> > > > 	nec_t *nec;
> > > >
> > > > and replace the functions above as:
> > > >
> > > > 	void f(char *data)
> > > > 	{
> > > > 		data[0] = 0; // Does NOT change
> > > > 	}
> > > >
> > > > 	void g()
> > > > 	{
> > > > 		nec->data.a = 0; // This DOES change
> > > > 	}
> > > >
> > > > With a rule something like this:
> > > >
> > > > 	@ rule1 @
> > > > 	typedef data_t;
> > > > 	type T = {data_t};
> > > > 	identifier I = {data};
> > >
> > > This means that your variable I should always be called "data".  Is that
> > > what you intended?
> > >
> > > You should be able to do
> > >
> > > idexpression data_t I = {data};
> > >
> > > Then you want to use the name in a structure field.  Te problem is that a
> > > structure field is not an expression, it is an identifier.  So you have to
> > > make the match in two ways:
> > >
> > > @@
> > > idexpression data_t I = {data};
> > > identifier j;
> > > @@
> > >
> > > -I@j
> > > +nec->j
> >
> > Thanks Julia, that seems to work (I added `typedef data_t;` to the .cocci
> > file).
> >
>
>
> Ok so this worked in the simple example .c file:
> 	@ rule1 @
> 	typedef data_t;
> 	global idexpression data_t I = {data};
> 	identifier j;
> 	@@
> 	-I@j
> 	+nec->j
>
> But when I try it on the actual code base I get this:
> 	]# spatch --sp-file nec-refactor2.cocci src/xnec2c.c
> 	init_defs_builtins: /usr/local/coccinelle-git/bin/lib/coccinelle/standard.h
> 	(ONCE) Expected tokens data_t
> 	Skipping: src/xnec2c.c
>
> I have tried:
>   * adding `-I src/`
>   * adding `--include src/common.h --include src/shared.h` where data_t is defined.
>   * adding --include-headers-for-types
>   * adding --recursive-includes
>   * Removing the `global` specifier on the idexpression.
>
> None of these seem to work, they all skip with the "(ONCE) Expected tokens data_t" error.
>
> However, if I hack "data_t data;" into the top of xnec2c.c then it works.
>
> There seems to be a problem finding the `data_t data` definition through the headers.
>
> What should I do?  Here is the .c file if you want to take a look:

I think that the file selection is done independent of includes.  A
solution is to just disable the file selection:

--disable-worth-trying-opt

You will still need the headers so that the type of data can be determined
and the matching can take place.  If the connection to the relevant file
is complex and involves lots of includes, then it is probably best to use
--include.

Another approach could be to just say global idexpression d = {data}.
If there is only one global variable called data in the entire system,
this should be fine.

julia


> 	https://github.com/KJ7LNW/xnec2c/blob/master/src/xnec2c.c
>
> and the .h file with data_t:
> 	https://github.com/KJ7LNW/xnec2c/blob/master/src/shared.h#L219
>
> Here is the version:
>
> ]# spatch --version
> spatch version 1.1.1-00044-gb2a4b9b compiled with OCaml version 4.05.0
> Flags passed to the configure script: --prefix=/usr/local/coccinelle-git
> OCaml scripting support: yes
> Python scripting support: yes
> Syntax of regular expressions: PCRE
>
> > What does I@j mean?  Can you point me at documentation?
>
> -Eric
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [cocci] Can you match identifiers of a specific type?
  2022-03-01  6:13       ` Julia Lawall
@ 2022-03-02  2:55         ` Eric Wheeler
  2022-03-02  7:28           ` Julia Lawall
  0 siblings, 1 reply; 8+ messages in thread
From: Eric Wheeler @ 2022-03-02  2:55 UTC (permalink / raw)
  To: Julia Lawall; +Cc: cocci

On Tue, 1 Mar 2022, Julia Lawall wrote:
> On Mon, 28 Feb 2022, Eric Wheeler wrote:
> > On Mon, 28 Feb 2022, Eric Wheeler wrote:
> > > On Mon, 28 Feb 2022, Julia Lawall wrote:
> > > > On Sun, 27 Feb 2022, Eric Wheeler wrote:
> > > >
> > > > > Hello,
> > > > >
> > > > > Can I match only specific identifier types and names where the type is a
> > > > > typedef? I've been reading as much as I can about Coccinelle but I've not
> > > > > found a way to do it.
> > > > >
> > > > > I'm trying to move global calculation structures into its own typedef
> > > > > structure to create a thread-safe environment where multiple threads can
> > > > > work on different struct instances.  Right now the code works only on
> > > > > static global values so parallelism is not possible without fork()ing.
> > > > > (This is for the www.xnec2c.org project.)
> > > > >
> > > > > The code that looks pretty close to the following:
> > > > >
> > > > > 	// Globals
> > > > > 	typedef struct {
> > > > > 		int a;
> > > > > 	} data_t
> > > > >
> > > > > 	data_t data;
> > > > >
> > > > > 	void f(char *data)
> > > > > 	{
> > > > > 		data[0] = 0; // parameter
> > > > > 	}
> > > > >
> > > > > 	void g()
> > > > > 	{
> > > > > 		data.a = 0; // global
> > > > > 	}
> > > > >
> > > > > I want to put all of the global 'data' variables of type 'data_t' into a
> > > > > new structure as follows:
> > > > >
> > > > > 	typedef struct {
> > > > > 		data_t data;
> > > > > 		// and many others...
> > > > > 	} nec_t;
> > > > >
> > > > > 	nec_t *nec;
> > > > >
> > > > > and replace the functions above as:
> > > > >
> > > > > 	void f(char *data)
> > > > > 	{
> > > > > 		data[0] = 0; // Does NOT change
> > > > > 	}
> > > > >
> > > > > 	void g()
> > > > > 	{
> > > > > 		nec->data.a = 0; // This DOES change
> > > > > 	}
> > > > >
> > > > > With a rule something like this:
> > > > >
> > > > > 	@ rule1 @
> > > > > 	typedef data_t;
> > > > > 	type T = {data_t};
> > > > > 	identifier I = {data};
> > > >
> > > > This means that your variable I should always be called "data".  Is that
> > > > what you intended?
> > > >
> > > > You should be able to do
> > > >
> > > > idexpression data_t I = {data};
> > > >
> > > > Then you want to use the name in a structure field.  Te problem is that a
> > > > structure field is not an expression, it is an identifier.  So you have to
> > > > make the match in two ways:
> > > >
> > > > @@
> > > > idexpression data_t I = {data};
> > > > identifier j;
> > > > @@
> > > >
> > > > -I@j
> > > > +nec->j
> > >
> > > Thanks Julia, that seems to work (I added `typedef data_t;` to the .cocci
> > > file).
> > >
> >
> >
> > Ok so this worked in the simple example .c file:
> > 	@ rule1 @
> > 	typedef data_t;
> > 	global idexpression data_t I = {data};
> > 	identifier j;
> > 	@@
> > 	-I@j
> > 	+nec->j
> >
> > But when I try it on the actual code base I get this:
> > 	]# spatch --sp-file nec-refactor2.cocci src/xnec2c.c
> > 	init_defs_builtins: /usr/local/coccinelle-git/bin/lib/coccinelle/standard.h
> > 	(ONCE) Expected tokens data_t
> > 	Skipping: src/xnec2c.c
> >
> > I have tried:
> >   * adding `-I src/`
> >   * adding `--include src/common.h --include src/shared.h` where data_t is defined.
> >   * adding --include-headers-for-types
> >   * adding --recursive-includes
> >   * Removing the `global` specifier on the idexpression.
> >
> > None of these seem to work, they all skip with the "(ONCE) Expected tokens data_t" error.
> >
> > However, if I hack "data_t data;" into the top of xnec2c.c then it works.
> >
> > There seems to be a problem finding the `data_t data` definition through the headers.
> >
> > What should I do?  Here is the .c file if you want to take a look:
> 
> I think that the file selection is done independent of includes.  A
> solution is to just disable the file selection:
> 
> --disable-worth-trying-opt
>
> You will still need the headers so that the type of data can be determined
> and the matching can take place.  If the connection to the relevant file
> is complex and involves lots of includes, then it is probably best to use
> --include.

--disable-worth-trying-opt option didn't seem to help, maybe I missed 
an include...but read on:

> Another approach could be to just say global idexpression d = {data}.
> If there is only one global variable called data in the entire system,
> this should be fine.

That worked!  I didn't realize idexpression can exclude the type.  All the 
variables I'm replacing are global and this time it didn't replace local 
versions of variables named "data".

The EM simulation completed after variable replacement, so while I still 
need to validate that the output data is the same, I think this is 
working.

Thanks again for your help!

-Eric

> 
> julia
> 
> 
> > 	https://github.com/KJ7LNW/xnec2c/blob/master/src/xnec2c.c
> >
> > and the .h file with data_t:
> > 	https://github.com/KJ7LNW/xnec2c/blob/master/src/shared.h#L219
> >
> > Here is the version:
> >
> > ]# spatch --version
> > spatch version 1.1.1-00044-gb2a4b9b compiled with OCaml version 4.05.0
> > Flags passed to the configure script: --prefix=/usr/local/coccinelle-git
> > OCaml scripting support: yes
> > Python scripting support: yes
> > Syntax of regular expressions: PCRE
> >
> > > What does I@j mean?  Can you point me at documentation?
> >
> > -Eric
> >
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [cocci] Can you match identifiers of a specific type?
  2022-03-02  2:55         ` Eric Wheeler
@ 2022-03-02  7:28           ` Julia Lawall
  0 siblings, 0 replies; 8+ messages in thread
From: Julia Lawall @ 2022-03-02  7:28 UTC (permalink / raw)
  To: Eric Wheeler; +Cc: cocci



On Tue, 1 Mar 2022, Eric Wheeler wrote:

> On Tue, 1 Mar 2022, Julia Lawall wrote:
> > On Mon, 28 Feb 2022, Eric Wheeler wrote:
> > > On Mon, 28 Feb 2022, Eric Wheeler wrote:
> > > > On Mon, 28 Feb 2022, Julia Lawall wrote:
> > > > > On Sun, 27 Feb 2022, Eric Wheeler wrote:
> > > > >
> > > > > > Hello,
> > > > > >
> > > > > > Can I match only specific identifier types and names where the type is a
> > > > > > typedef? I've been reading as much as I can about Coccinelle but I've not
> > > > > > found a way to do it.
> > > > > >
> > > > > > I'm trying to move global calculation structures into its own typedef
> > > > > > structure to create a thread-safe environment where multiple threads can
> > > > > > work on different struct instances.  Right now the code works only on
> > > > > > static global values so parallelism is not possible without fork()ing.
> > > > > > (This is for the www.xnec2c.org project.)
> > > > > >
> > > > > > The code that looks pretty close to the following:
> > > > > >
> > > > > > 	// Globals
> > > > > > 	typedef struct {
> > > > > > 		int a;
> > > > > > 	} data_t
> > > > > >
> > > > > > 	data_t data;
> > > > > >
> > > > > > 	void f(char *data)
> > > > > > 	{
> > > > > > 		data[0] = 0; // parameter
> > > > > > 	}
> > > > > >
> > > > > > 	void g()
> > > > > > 	{
> > > > > > 		data.a = 0; // global
> > > > > > 	}
> > > > > >
> > > > > > I want to put all of the global 'data' variables of type 'data_t' into a
> > > > > > new structure as follows:
> > > > > >
> > > > > > 	typedef struct {
> > > > > > 		data_t data;
> > > > > > 		// and many others...
> > > > > > 	} nec_t;
> > > > > >
> > > > > > 	nec_t *nec;
> > > > > >
> > > > > > and replace the functions above as:
> > > > > >
> > > > > > 	void f(char *data)
> > > > > > 	{
> > > > > > 		data[0] = 0; // Does NOT change
> > > > > > 	}
> > > > > >
> > > > > > 	void g()
> > > > > > 	{
> > > > > > 		nec->data.a = 0; // This DOES change
> > > > > > 	}
> > > > > >
> > > > > > With a rule something like this:
> > > > > >
> > > > > > 	@ rule1 @
> > > > > > 	typedef data_t;
> > > > > > 	type T = {data_t};
> > > > > > 	identifier I = {data};
> > > > >
> > > > > This means that your variable I should always be called "data".  Is that
> > > > > what you intended?
> > > > >
> > > > > You should be able to do
> > > > >
> > > > > idexpression data_t I = {data};
> > > > >
> > > > > Then you want to use the name in a structure field.  Te problem is that a
> > > > > structure field is not an expression, it is an identifier.  So you have to
> > > > > make the match in two ways:
> > > > >
> > > > > @@
> > > > > idexpression data_t I = {data};
> > > > > identifier j;
> > > > > @@
> > > > >
> > > > > -I@j
> > > > > +nec->j
> > > >
> > > > Thanks Julia, that seems to work (I added `typedef data_t;` to the .cocci
> > > > file).
> > > >
> > >
> > >
> > > Ok so this worked in the simple example .c file:
> > > 	@ rule1 @
> > > 	typedef data_t;
> > > 	global idexpression data_t I = {data};
> > > 	identifier j;
> > > 	@@
> > > 	-I@j
> > > 	+nec->j
> > >
> > > But when I try it on the actual code base I get this:
> > > 	]# spatch --sp-file nec-refactor2.cocci src/xnec2c.c
> > > 	init_defs_builtins: /usr/local/coccinelle-git/bin/lib/coccinelle/standard.h
> > > 	(ONCE) Expected tokens data_t
> > > 	Skipping: src/xnec2c.c
> > >
> > > I have tried:
> > >   * adding `-I src/`
> > >   * adding `--include src/common.h --include src/shared.h` where data_t is defined.
> > >   * adding --include-headers-for-types
> > >   * adding --recursive-includes
> > >   * Removing the `global` specifier on the idexpression.
> > >
> > > None of these seem to work, they all skip with the "(ONCE) Expected tokens data_t" error.
> > >
> > > However, if I hack "data_t data;" into the top of xnec2c.c then it works.
> > >
> > > There seems to be a problem finding the `data_t data` definition through the headers.
> > >
> > > What should I do?  Here is the .c file if you want to take a look:
> >
> > I think that the file selection is done independent of includes.  A
> > solution is to just disable the file selection:
> >
> > --disable-worth-trying-opt
> >
> > You will still need the headers so that the type of data can be determined
> > and the matching can take place.  If the connection to the relevant file
> > is complex and involves lots of includes, then it is probably best to use
> > --include.
>
> --disable-worth-trying-opt option didn't seem to help, maybe I missed
> an include...but read on:

Thanks for the report. I will check on why it does not work.

julia

>
> > Another approach could be to just say global idexpression d = {data}.
> > If there is only one global variable called data in the entire system,
> > this should be fine.
>
> That worked!  I didn't realize idexpression can exclude the type.  All the
> variables I'm replacing are global and this time it didn't replace local
> versions of variables named "data".
>
> The EM simulation completed after variable replacement, so while I still
> need to validate that the output data is the same, I think this is
> working.
>
> Thanks again for your help!
>
> -Eric
>
> >
> > julia
> >
> >
> > > 	https://github.com/KJ7LNW/xnec2c/blob/master/src/xnec2c.c
> > >
> > > and the .h file with data_t:
> > > 	https://github.com/KJ7LNW/xnec2c/blob/master/src/shared.h#L219
> > >
> > > Here is the version:
> > >
> > > ]# spatch --version
> > > spatch version 1.1.1-00044-gb2a4b9b compiled with OCaml version 4.05.0
> > > Flags passed to the configure script: --prefix=/usr/local/coccinelle-git
> > > OCaml scripting support: yes
> > > Python scripting support: yes
> > > Syntax of regular expressions: PCRE
> > >
> > > > What does I@j mean?  Can you point me at documentation?
> > >
> > > -Eric
> > >
> >
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2022-03-02  7:28 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-28  4:24 [cocci] Can you match identifiers of a specific type? Eric Wheeler
2022-02-28  6:08 ` Julia Lawall
2022-03-01  1:28   ` Eric Wheeler
2022-03-01  2:01     ` Eric Wheeler
2022-03-01  6:13       ` Julia Lawall
2022-03-02  2:55         ` Eric Wheeler
2022-03-02  7:28           ` Julia Lawall
2022-03-01  6:09     ` Julia Lawall

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.