* [Cocci] Q: stdint format specifiers
@ 2016-08-04 16:30 Johann Klammer
2016-08-04 16:33 ` Julia Lawall
0 siblings, 1 reply; 8+ messages in thread
From: Johann Klammer @ 2016-08-04 16:30 UTC (permalink / raw)
To: cocci
Does anyone have a coccinelle script to fixup *printf format specifiers to
those pesky PRI*** ones? I could not find one on coccinellery <http://coccinellery.org/>.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Cocci] Q: stdint format specifiers
2016-08-04 16:30 [Cocci] Q: stdint format specifiers Johann Klammer
@ 2016-08-04 16:33 ` Julia Lawall
2016-08-04 16:46 ` Johann Klammer
0 siblings, 1 reply; 8+ messages in thread
From: Julia Lawall @ 2016-08-04 16:33 UTC (permalink / raw)
To: cocci
On Thu, 4 Aug 2016, Johann Klammer wrote:
> Does anyone have a coccinelle script to fixup *printf format specifiers to
> those pesky PRI*** ones? I could not find one on coccinellery <http://coccinellery.org/>.
Could you give a more precise example of what you want to do?
thanks,
julia
>
> _______________________________________________
> Cocci mailing list
> Cocci at systeme.lip6.fr
> https://systeme.lip6.fr/mailman/listinfo/cocci
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Cocci] Q: stdint format specifiers
2016-08-04 16:33 ` Julia Lawall
@ 2016-08-04 16:46 ` Johann Klammer
2016-08-04 17:10 ` Julia Lawall
0 siblings, 1 reply; 8+ messages in thread
From: Johann Klammer @ 2016-08-04 16:46 UTC (permalink / raw)
To: cocci
On 08/04/2016 06:33 PM, Julia Lawall wrote:
> On Thu, 4 Aug 2016, Johann Klammer wrote:
>
>> Does anyone have a coccinelle script to fixup *printf format specifiers to
>> those pesky PRI*** ones? I could not find one on coccinellery <http://coccinellery.org/>.
>
> Could you give a more precise example of what you want to do?
>
> thanks,
> julia
I was getting a gcc warning:
> make[1]: Entering directory '/home/klammerj/projects/FPGA/src/fpgatools/libs'
> CC floorplan.o
> floorplan.c: In function ?printf_LOGIC?:
> floorplan.c:369:17: warning: format ?%lX? expects argument of type ?long unsigned int?, but argument 6 has type ?uint64_t {aka long long unsigned int}? [-Wformat=]
> fprintf(f, "%s%s\"%c6_lut_val\" : \"0x%016lX\" }",
I've fixed those by hand, but I think not all cases will give
warnings, because int etc are often aliases for those stdint things.
..same width signedness..
Thus I'd like to run coccinelle on the .c files, to look for printfs
which have uintxx intxx type arguments and replace the corresponding
specifiers by the ones suggested in the C standard:
> 7.8.1 Macros for format specifiers
> 1 Each of the following object-like macros expands to a character string literal containing a
> conversion specifier, possibly modified by a length modifier, suitable for use within the
> format argument of a formatted input/output function when converting the corresponding
> integer type. These macro names have the general form of PRI (character string literals
> for the fprintf and fwprintf family) or SCN (character string literals for the
> fscanf and fwscanf family), 220) followed by the conversion specifier, followed by a
> name corresponding to a similar type name in 7.20.1. In these names, N represents the
> width of the type as described in 7.20.1. For example, PRIdFAST32 can be used in a
> format string to print the value of an integer of type int_fast32_t.
> 2 The fprintf macros for signed integers are:
> PRIdN
> PRIiN
> 3
> PRIdFASTN
> PRIiFASTN
> PRIdMAX
> PRIiMAX PRIdPTR
> PRIiPTR
> PRIoMAX
> PRIuMAX
> PRIxMAX
> PRIXMAX PRIoPTR
> PRIuPTR
> PRIxPTR
> PRIXPTR
> The fprintf macros for unsigned integers are:
> PRIoN
> PRIuN
> PRIxN
> PRIXN
> 4
> PRIdLEASTN
> PRIiLEASTN
> PRIoLEASTN
> PRIuLEASTN
> PRIxLEASTN
> PRIXLEASTN
> PRIoFASTN
> PRIuFASTN
> PRIxFASTN
> PRIXFASTN
> The fscanf macros for signed integers are:
[...]
result something along the lines of:
> diff --git a/libs/floorplan.c b/libs/floorplan.c
> index 2b9b27a..fb27edb 100644
> --- a/libs/floorplan.c
> +++ b/libs/floorplan.c
> @@ -366,7 +366,7 @@ int printf_LOGIC(FILE* f, struct fpga_model* model,
> if (cfg->a2d[j].flags & LUT6VAL_SET) {
> RC_ASSERT(model, !ULL_HIGH32(cfg->a2d[j].lut6_val));
> if (print_hex_vals)
> - fprintf(f, "%s%s\"%c6_lut_val\" : \"0x%016lX\" }",
> + fprintf(f, "%s%s\"%c6_lut_val\" : \"0x%016"PRIX64"\" }",
> first_line ? "" : ",\n", pref, 'A'+j, cfg->a2d[j].lut6_val);
> else {
> str = bool_bits2str(cfg->a2d[j].lut6_val, 32);
> @@ -389,7 +389,7 @@ int printf_LOGIC(FILE* f, struct fpga_model* model,
> } else {
> if (cfg->a2d[j].flags & LUT6VAL_SET) {
> if (print_hex_vals)
> - fprintf(f, "%s%s\"%c6_lut_val\" : \"0x%016lX\" }",
> + fprintf(f, "%s%s\"%c6_lut_val\" : \"0x%016"PRIX64"\" }",
> first_line ? "" : ",\n", pref, 'A'+j, cfg->a2d[j].lut6_val);
> else {
> str = bool_bits2str(cfg->a2d[j].lut6_val, 64);
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Cocci] Q: stdint format specifiers
2016-08-04 16:46 ` Johann Klammer
@ 2016-08-04 17:10 ` Julia Lawall
2016-08-04 20:55 ` Johann Klammer
0 siblings, 1 reply; 8+ messages in thread
From: Julia Lawall @ 2016-08-04 17:10 UTC (permalink / raw)
To: cocci
On Thu, 4 Aug 2016, Johann Klammer wrote:
> On 08/04/2016 06:33 PM, Julia Lawall wrote:
> > On Thu, 4 Aug 2016, Johann Klammer wrote:
> >
> >> Does anyone have a coccinelle script to fixup *printf format specifiers to
> >> those pesky PRI*** ones? I could not find one on coccinellery <http://coccinellery.org/>.
> >
> > Could you give a more precise example of what you want to do?
> >
> > thanks,
> > julia
>
> I was getting a gcc warning:
>
> > make[1]: Entering directory '/home/klammerj/projects/FPGA/src/fpgatools/libs'
> > CC floorplan.o
> > floorplan.c: In function ?printf_LOGIC?:
> > floorplan.c:369:17: warning: format ?%lX? expects argument of type ?long unsigned int?, but argument 6 has type ?uint64_t {aka long long unsigned int}? [-Wformat=]
> > fprintf(f, "%s%s\"%c6_lut_val\" : \"0x%016lX\" }",
>
> I've fixed those by hand, but I think not all cases will give
> warnings, because int etc are often aliases for those stdint things.
> ..same width signedness..
> Thus I'd like to run coccinelle on the .c files, to look for printfs
> which have uintxx intxx type arguments and replace the corresponding
> specifiers by the ones suggested in the C standard:
Coccinelle makes a small effort to help with parsing format strings, but
it doesn't support the PRI things you mention. What you could do is
something like this:
@r@
{suspicious_type1,suspicious_type2,...} x;
type T;
T y;
expression list[n] es;
constant char[] c;
identifier f;
position p;
@@
f(...,c at p,es,x at y,...)
@script:python s@
T << r.T; // the type of the argument of interest
c << r.c; // the format string
n << r.n; // the offset of the argument of interest, counted from 0
c2;
@@
Now use python to compute a new format string for your type.
coccinelle.c2 = the format string with extra quotes around it
@@
expression e;
position r.p;
identifier s.c2;
@@
- e at p
+ c2
Unfortunately, however, this will not work if you have a print with two
suspicious arguments. Indeed, Coccinelle will completely crash on that
file, because it has no way to merge two changes made for independent
reasons.
If the problem arises frequently and you are willing to do some work by
hand, then you could just let the format strings accumulate before the
calls and replace/merge them by hand. The third rule would become:
@@
expression e;
position r.p;
identifier r.f,s.c2;
@@
++c2;
f(...,e at p,...);
If that is not acceptable, you can use a hash table to collect all the
changes that are needed in a particular format string, and then work on
them all at once. The second rule would put the T n p and c information
in a hashtable (you would need to add the declaration p << r.p; for this),
and then you would need another python rule with only the metavariable p
<< r.p; and the variale c2 that would collect the information relevant to
the position p from the hash table and make the appropriate format string.
The last rule would be just
@@
expression e;
position r.p;
identifier s.c2;
@@
- e@p
+ c2
in that case.
I can elaborate more if needed on any of the above options.
julia
>
>
>
> > 7.8.1 Macros for format specifiers
> > 1 Each of the following object-like macros expands to a character string literal containing a
> > conversion specifier, possibly modified by a length modifier, suitable for use within the
> > format argument of a formatted input/output function when converting the corresponding
> > integer type. These macro names have the general form of PRI (character string literals
> > for the fprintf and fwprintf family) or SCN (character string literals for the
> > fscanf and fwscanf family), 220) followed by the conversion specifier, followed by a
> > name corresponding to a similar type name in 7.20.1. In these names, N represents the
> > width of the type as described in 7.20.1. For example, PRIdFAST32 can be used in a
> > format string to print the value of an integer of type int_fast32_t.
> > 2 The fprintf macros for signed integers are:
> > PRIdN
> > PRIiN
> > 3
> > PRIdFASTN
> > PRIiFASTN
> > PRIdMAX
> > PRIiMAX PRIdPTR
> > PRIiPTR
> > PRIoMAX
> > PRIuMAX
> > PRIxMAX
> > PRIXMAX PRIoPTR
> > PRIuPTR
> > PRIxPTR
> > PRIXPTR
> > The fprintf macros for unsigned integers are:
> > PRIoN
> > PRIuN
> > PRIxN
> > PRIXN
> > 4
> > PRIdLEASTN
> > PRIiLEASTN
> > PRIoLEASTN
> > PRIuLEASTN
> > PRIxLEASTN
> > PRIXLEASTN
> > PRIoFASTN
> > PRIuFASTN
> > PRIxFASTN
> > PRIXFASTN
> > The fscanf macros for signed integers are:
> [...]
>
> result something along the lines of:
>
> > diff --git a/libs/floorplan.c b/libs/floorplan.c
> > index 2b9b27a..fb27edb 100644
> > --- a/libs/floorplan.c
> > +++ b/libs/floorplan.c
> > @@ -366,7 +366,7 @@ int printf_LOGIC(FILE* f, struct fpga_model* model,
> > if (cfg->a2d[j].flags & LUT6VAL_SET) {
> > RC_ASSERT(model, !ULL_HIGH32(cfg->a2d[j].lut6_val));
> > if (print_hex_vals)
> > - fprintf(f, "%s%s\"%c6_lut_val\" : \"0x%016lX\" }",
> > + fprintf(f, "%s%s\"%c6_lut_val\" : \"0x%016"PRIX64"\" }",
> > first_line ? "" : ",\n", pref, 'A'+j, cfg->a2d[j].lut6_val);
> > else {
> > str = bool_bits2str(cfg->a2d[j].lut6_val, 32);
> > @@ -389,7 +389,7 @@ int printf_LOGIC(FILE* f, struct fpga_model* model,
> > } else {
> > if (cfg->a2d[j].flags & LUT6VAL_SET) {
> > if (print_hex_vals)
> > - fprintf(f, "%s%s\"%c6_lut_val\" : \"0x%016lX\" }",
> > + fprintf(f, "%s%s\"%c6_lut_val\" : \"0x%016"PRIX64"\" }",
> > first_line ? "" : ",\n", pref, 'A'+j, cfg->a2d[j].lut6_val);
> > else {
> > str = bool_bits2str(cfg->a2d[j].lut6_val, 64);
>
> _______________________________________________
> Cocci mailing list
> Cocci at systeme.lip6.fr
> https://systeme.lip6.fr/mailman/listinfo/cocci
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Cocci] Q: stdint format specifiers
2016-08-04 17:10 ` Julia Lawall
@ 2016-08-04 20:55 ` Johann Klammer
2016-08-04 21:11 ` Julia Lawall
0 siblings, 1 reply; 8+ messages in thread
From: Johann Klammer @ 2016-08-04 20:55 UTC (permalink / raw)
To: cocci
Mkay...
I tried.
> @r@
> {int8_t,int16_t,int32_t,int64_t,
> uint8_t,uint16_t,uint32_t,uint64_t} x;
> type T;
> T y;
> expression list[n] es;
> constant char[] c;
> identifier f;
> position p;
> @@
>
> f(...,c at p,es,x at y,...)
>
> @script:python s@
> T << r.T; // the type of the argument of interest
> c << r.c; // the format string
> n << r.n; // the offset of the argument of interest, counted from 0
> c2;
> @@
fails with:
> ~/projects/FPGA/src/fpgatools/libs$ spatch --sp-file ../pri.sp ./*.c
> init_defs_builtins: /usr/lib/coccinelle/standard.h
> 5 11
> Fatal error: exception Failure("meta: parse error: \n = File \"../pri.sp\", line 2, column 1, charpos = 5\n around = 'int8_t', whole content = {int8_t,int16_t,int32_t,int64_t,\n")
looking at the main_grammar.pdf reveals that the typedefs are resolved....
Is there a way to match the original typename?
If someone actually wrote long int, the lX is perfectly fine.
if it's one of the stdints it'll change on different subarchs, so it needs the PRI*.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Cocci] Q: stdint format specifiers
2016-08-04 20:55 ` Johann Klammer
@ 2016-08-04 21:11 ` Julia Lawall
2016-08-07 22:35 ` [Cocci] [Solved] " Johann Klammer
0 siblings, 1 reply; 8+ messages in thread
From: Julia Lawall @ 2016-08-04 21:11 UTC (permalink / raw)
To: cocci
On Thu, 4 Aug 2016, Johann Klammer wrote:
> Mkay...
>
> I tried.
> > @r@
> > {int8_t,int16_t,int32_t,int64_t,
> > uint8_t,uint16_t,uint32_t,uint64_t} x;
> > type T;
> > T y;
> > expression list[n] es;
> > constant char[] c;
> > identifier f;
> > position p;
> > @@
> >
> > f(...,c at p,es,x at y,...)
> >
> > @script:python s@
> > T << r.T; // the type of the argument of interest
> > c << r.c; // the format string
> > n << r.n; // the offset of the argument of interest, counted from 0
> > c2;
> > @@
> fails with:
>
> > ~/projects/FPGA/src/fpgatools/libs$ spatch --sp-file ../pri.sp ./*.c
> > init_defs_builtins: /usr/lib/coccinelle/standard.h
> > 5 11
> > Fatal error: exception Failure("meta: parse error: \n = File \"../pri.sp\", line 2, column 1, charpos = 5\n around = 'int8_t', whole content = {int8_t,int16_t,int32_t,int64_t,\n")
Add typedef int8_t,int16_t,int32_t,int64_t,etc; before the definition of
x.
> looking at the main_grammar.pdf reveals that the typedefs are resolved....
I'm not sure to understand what you mean by "resolved". If Coccinelle can
see the typedef definition, then it will keep track of both the typedef
name and the underlying type name. But by default, Coccinelle only picks
up on header files that are in the same directory as the .c file and
header files in the include path that have the same name as the .c file.
To get more, you need to give the option --all-includes (all explicitly
mentioned header files) or --recursive-includes (also header files that
are included by other header files). But both of these options are likely
to cost a lot in performance. So if you are ok with the type names as
they are written in the code, you are better off. If you want to be sure
that Coccinelle won't find a definition of a typdef in an include file,
you can use --no-includes.
But note that include files also may contain structure type definitions,
which may also be useful.
julia
> Is there a way to match the original typename?
> If someone actually wrote long int, the lX is perfectly fine.
> if it's one of the stdints it'll change on different subarchs, so it needs the PRI*.
>
>
>
> _______________________________________________
> Cocci mailing list
> Cocci at systeme.lip6.fr
> https://systeme.lip6.fr/mailman/listinfo/cocci
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Cocci] [Solved] Q: stdint format specifiers
2016-08-04 21:11 ` Julia Lawall
@ 2016-08-07 22:35 ` Johann Klammer
[not found] ` <alpine.DEB.2.10.1608080744490.3335@hadrien>
0 siblings, 1 reply; 8+ messages in thread
From: Johann Klammer @ 2016-08-07 22:35 UTC (permalink / raw)
To: cocci
//kinda works now ..kinda
@initialize:python@
@@
coccinelle.pd={}
@r@
typedef int8_t,int16_t,int32_t,int64_t,uint8_t,uint16_t,uint32_t,uint64_t;
{int8_t,int16_t,int32_t,int64_t,
uint8_t,uint16_t,uint32_t,uint64_t} x;
type T;
T y;
expression list[n] es;
constant char[] c;
identifier f =~ ".*printf$";
position p;
@@
f(...,c at p,es,x at y,...)
@script:python collect@
p << r.p; // position
f << r.f; // func name
T << r.T; // the type of the argument of interest
c << r.c; // the format string
n << r.n; // the offset of the argument of interest, counted from 0
@@
import re
trex = re.compile("((uint\\S*_t)|(int\\S*_t))")//to match only typename(no qualifiers)
m=trex.search(T)
t=m.group(1)
ps=("%s:(%s,%s),(%s,%s)::" % (p[0].file,p[0].line,p[0].column,p[0].line_end,p[0].column_end))
if (ps in coccinelle.pd):
coccinelle.pd[ps][1][n]=t
else:
coccinelle.pd[ps]=[c,{n:t}]
@script:python fmt@
p << r.p; // position
c2;
@@
ps=("%s:(%s,%s),(%s,%s)::" % (p[0].file,p[0].line,p[0].column,p[0].line_end,p[0].column_end))
in_str=False//inside string lit
in_pesc=False//seen a %
in_besc=False//seen a \
tps=coccinelle.pd[ps][1]//the types
import re
prex = re.compile("\s*(PRI([diouxX])(8|16|32|64))\s*")//to match existing ones...
pmap= {
"int8_t" :{"c":"\"c\"","d":"PRId8", "i":"PRIi8", "o":"PRIo8", "u":"PRIu8", "x":"PRIx8", "X":"PRIX8"},
"int16_t" :{"d":"PRId16", "i":"PRIi16", "o":"PRIo16", "u":"PRIu16", "x":"PRIx16", "X":"PRIX16"},
"int32_t" :{"d":"PRId32", "i":"PRIi32", "o":"PRIo32", "u":"PRIu32", "x":"PRIx32", "X":"PRIX32"},
"int64_t" :{"d":"PRId64", "i":"PRIi64", "o":"PRIo64", "u":"PRIu64", "x":"PRIx64", "X":"PRIX64"},
"uint8_t" :{"c":"\"c\"","d":"PRIu8", "i":"PRIu8", "o":"PRIo8", "u":"PRIu8", "x":"PRIx8", "X":"PRIX8"},
"uint16_t":{"d":"PRIu16", "i":"PRIu16", "o":"PRIo16", "u":"PRIu16", "x":"PRIx16", "X":"PRIX16"},
"uint32_t":{"d":"PRIu32", "i":"PRIu32", "o":"PRIo32", "u":"PRIu32", "x":"PRIx32", "X":"PRIX32"},
"uint64_t":{"d":"PRIu64", "i":"PRIu64", "o":"PRIo64", "u":"PRIu64", "x":"PRIx64", "X":"PRIX64"},
}
fmt_ctr=0//some index
str_a=coccinelle.pd[ps][0]
coccinelle.c2=""
i=0
a=-1
while True:
if i>=len(str_a):
break
c=str_a[i]
if in_str==True:
if in_pesc==True:
if c=="%":
in_pesc=False
coccinelle.c2="%s%s" % (coccinelle.c2,c)
i+=1
else:
if c in "hlLqjzt"://size modifiers. mem index of first one
if a==-1:
a=i
i+=1
elif c in "diouxXEeFfGgAacsCSP":
in_pesc=False
if a==-1:
a=i
fs="%s" % (fmt_ctr)
if fs in tps:
coccinelle.c2="%s\"%s\"" % (coccinelle.c2,pmap[tps[fs]][c])
else:
coccinelle.c2="%s%s" % (coccinelle.c2,str_a[a:(i+1)])
fmt_ctr+=1
i+=1
else://just append the prec stuff...
if c=="\"":
in_str=False
coccinelle.c2="%s%s" % (coccinelle.c2,c)
i+=1
elif in_besc==True:
in_besc=False
coccinelle.c2="%s%s" % (coccinelle.c2,c)
i+=1
else:
if c=="\\":
in_besc=True
elif c=="%":
in_pesc=True
a=-1
elif c=="\"":
in_str=False
coccinelle.c2="%s%s" % (coccinelle.c2,c)
i+=1
else:
if c=="\"":
in_str=True
coccinelle.c2="%s%s" % (coccinelle.c2,c)
i+=1;
else:
if in_pesc==True:
m=prex.match(str_a[i:])
fs="%s" % (fmt_ctr)
if m and (fs in tps):
i+=m.end();
coccinelle.c2="%s%s" % (coccinelle.c2,pmap[tps[fs]][m.group(2)])
fmt_ctr+=1
in_pesc=False
else:
coccinelle.c2="%s%s" % (coccinelle.c2,c)
i+=1
else:
coccinelle.c2="%s%s" % (coccinelle.c2,c)
i+=1;
@q@
expression e;
position r.p;
identifier fmt.c2;
@@
- e at p
+ c2
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Cocci] [Solved] Q: stdint format specifiers
[not found] ` <alpine.DEB.2.10.1608080744490.3335@hadrien>
@ 2016-08-08 10:48 ` Johann Klammer
0 siblings, 0 replies; 8+ messages in thread
From: Johann Klammer @ 2016-08-08 10:48 UTC (permalink / raw)
To: cocci
On 08/08/2016 07:46 AM, Julia Lawall wrote:
> On Mon, 8 Aug 2016, Johann Klammer wrote:
>
>> //kinda works now ..kinda
>
> It does rather lack elegance...
>
> Does your software always use print variants for printing? If there are
> some wrappers, you could see what happens without the constraint on f.
>
> julia
>
No, and I had to change that pattern a few times.
the thing is that scanf variants use different macros.
and I can't really see what except for the func name
would prevent me from matching those.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2016-08-08 10:48 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-04 16:30 [Cocci] Q: stdint format specifiers Johann Klammer
2016-08-04 16:33 ` Julia Lawall
2016-08-04 16:46 ` Johann Klammer
2016-08-04 17:10 ` Julia Lawall
2016-08-04 20:55 ` Johann Klammer
2016-08-04 21:11 ` Julia Lawall
2016-08-07 22:35 ` [Cocci] [Solved] " Johann Klammer
[not found] ` <alpine.DEB.2.10.1608080744490.3335@hadrien>
2016-08-08 10:48 ` Johann Klammer
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.