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