1/// Detect BQ27XXX_DATA structures with identical registers, dm registers or
2/// properties.
3//# Doesn't unfold macros used in register or property fields.
4//# Requires OCaml scripting
5///
6// Confidence: High
7// Copyright: (C) 2017 Julia Lawall, Inria/LIP6, GPLv2.
8// URL: http://coccinelle.lip6.fr/
9// Requires: 1.0.7
10// Keywords: BQ27XXX_DATA
11
12virtual report
13
14@initialize:ocaml@
15@@
16
17let print_report p msg =
18  let p = List.hd p in
19  Printf.printf "%s:%d:%d-%d: %s" p.file p.line p.col p.col_end msg
20
21@str depends on report@
22type t;
23identifier i,i1,i2;
24expression e1,e2;
25@@
26
27t i[] = {
28  ...,
29  [e1] = BQ27XXX_DATA(i1,...),
30  ...,
31  [e2] = BQ27XXX_DATA(i2,...),
32  ...,
33};
34
35@script:ocaml tocheck@
36i1 << str.i1;
37i2 << str.i2;
38i1regs; i2regs;
39i1dmregs; i2dmregs;
40i1props; i2props;
41@@
42
43if not(i1 = i2)
44then
45  begin
46    i1regs := make_ident (i1 ^ "_regs");
47    i2regs := make_ident (i2 ^ "_regs");
48    i1dmregs := make_ident (i1 ^ "_dm_regs");
49    i2dmregs := make_ident (i2 ^ "_dm_regs");
50    i1props := make_ident (i1 ^ "_props");
51    i2props := make_ident (i2 ^ "_props")
52  end
53
54(* ---------------------------------------------------------------- *)
55
56@getregs1@
57typedef u8;
58identifier tocheck.i1regs;
59initializer list i1regs_vals;
60position p1;
61@@
62
63u8 i1regs@p1[...] = { i1regs_vals, };
64
65@getregs2@
66identifier tocheck.i2regs;
67initializer list i2regs_vals;
68position p2;
69@@
70
71u8 i2regs@p2[...] = { i2regs_vals, };
72
73@script:ocaml@
74(_,i1regs_vals) << getregs1.i1regs_vals;
75(_,i2regs_vals) << getregs2.i2regs_vals;
76i1regs << tocheck.i1regs;
77i2regs << tocheck.i2regs;
78p1 << getregs1.p1;
79p2 << getregs2.p2;
80@@
81
82if i1regs < i2regs &&
83   List.sort compare i1regs_vals = List.sort compare i2regs_vals
84then
85  let msg =
86    Printf.sprintf
87      "WARNING %s and %s (line %d) are identical\n"
88      i1regs i2regs (List.hd p2).line in
89  print_report p1 msg
90
91(* ---------------------------------------------------------------- *)
92
93@getdmregs1@
94identifier tocheck.i1dmregs;
95initializer list i1dmregs_vals;
96position p1;
97@@
98
99struct bq27xxx_dm_reg i1dmregs@p1[] = { i1dmregs_vals, };
100
101@getdmregs2@
102identifier tocheck.i2dmregs;
103initializer list i2dmregs_vals;
104position p2;
105@@
106
107struct bq27xxx_dm_reg i2dmregs@p2[] = { i2dmregs_vals, };
108
109@script:ocaml@
110(_,i1dmregs_vals) << getdmregs1.i1dmregs_vals;
111(_,i2dmregs_vals) << getdmregs2.i2dmregs_vals;
112i1dmregs << tocheck.i1dmregs;
113i2dmregs << tocheck.i2dmregs;
114p1 << getdmregs1.p1;
115p2 << getdmregs2.p2;
116@@
117
118if i1dmregs < i2dmregs &&
119   List.sort compare i1dmregs_vals = List.sort compare i2dmregs_vals
120then
121  let msg =
122    Printf.sprintf
123      "WARNING %s and %s (line %d) are identical\n"
124      i1dmregs i2dmregs (List.hd p2).line in
125  print_report p1 msg
126
127(* ---------------------------------------------------------------- *)
128
129@getprops1@
130identifier tocheck.i1props;
131initializer list[n1] i1props_vals;
132position p1;
133@@
134
135enum power_supply_property i1props@p1[] = { i1props_vals, };
136
137@getprops2@
138identifier tocheck.i2props;
139initializer list[n2] i2props_vals;
140position p2;
141@@
142
143enum power_supply_property i2props@p2[] = { i2props_vals, };
144
145@script:ocaml@
146(_,i1props_vals) << getprops1.i1props_vals;
147(_,i2props_vals) << getprops2.i2props_vals;
148i1props << tocheck.i1props;
149i2props << tocheck.i2props;
150p1 << getprops1.p1;
151p2 << getprops2.p2;
152@@
153
154if i1props < i2props &&
155   List.sort compare i1props_vals = List.sort compare i2props_vals
156then
157  let msg =
158    Printf.sprintf
159      "WARNING %s and %s (line %d) are identical\n"
160      i1props i2props (List.hd p2).line in
161  print_report p1 msg
162