5 (* For the moment I do only eq_type and not eq_expr, etc. The reason
6 * for eq_type is related to the typedef and struct isomorphism. Sometimes
7 * one use the typedef and sometimes the structname.
9 * TODO: should use the isomorphisms engine of julia.
10 * Maybe I can transform my ast_c in ast_cocci, and use julia's code ?
11 * Maybe I can add some Disj in my ast_c ?
20 type 'a matcher
= 'a
-> 'a
-> tin
-> 'a tout
24 ('a
-> (tin
-> 'b tout
)) ->
27 val (>&&>) : bool -> (tin
-> 'x tout
) -> (tin
-> 'x tout
)
29 val return
: 'a
-> tin
-> 'a tout
30 val fail
: tin
-> 'a tout
35 functor (X
: PARAM
) ->
38 type 'a matcher
= 'a
-> 'a
-> X.tin
-> 'a
X.tout
45 let (option: 'a matcher
-> ('a
option matcher
)) = fun f t1 t2
->
47 | (Some t1
, Some t2
) ->
51 | (None
, None
) -> return None
55 let same_s saopt sbopt
=
56 match saopt
, sbopt
with
58 | Some namea
, Some nameb
->
59 let sa = Ast_c.str_of_name namea
in
60 let sb = Ast_c.str_of_name nameb
in
65 let rec fullType a b
=
66 let ((qua
,iiqa
), tya
) = a
in
67 let ((qub
,iiqb
), tyb
) = b
in
68 (qua
.const
=:= qub
.const
&& qua
.volatile
=:= qub
.volatile
) >&&>
70 let (qu
,iiq
) = (qua
, iiqa
) in
71 typeC tya tyb
>>= (fun ty
->
82 | BaseType a
, BaseType b
->
83 a
=*= b
>&&> return (BaseType a
, iix)
84 | Pointer a
, Pointer b
->
85 fullType a b
>>= (fun x
-> return (Pointer x
, iix))
87 | StructUnionName
(sua
, sa), StructUnionName
(sub
, sb) ->
88 (sua
=*= sub
&& sa =$
= sb) >&&>
89 return (StructUnionName
(sua
, sa), iix)
91 | TypeName
(namea
, opta
), TypeName
(nameb
, optb
) ->
92 let sa = Ast_c.str_of_name namea
in
93 let sb = Ast_c.str_of_name nameb
in
95 (* assert compatible opta optb ? *)
96 (*option fullType opta optb*)
99 (match opta
, optb
with
108 return (TypeName
(namea
, opt), iix)
111 | Array
(ea
, a
), Array
(eb
,b
) ->
112 let get_option f
= function Some x
-> Some
(f x
) | None
-> None
in
113 let ea = get_option Lib_parsing_c.al_expr
ea in
114 let eb = get_option Lib_parsing_c.al_expr
eb in
115 ea =*= eb >&&> fullType a b
>>= (fun x
-> return (Array
(ea, x
), iix))
117 | FunctionType
(returna
, paramsa
), FunctionType
(returnb
, paramsb
) ->
118 let (tsa
, (ba
,iihas3dotsa
)) = paramsa
in
119 let (tsb
, (bb
,iihas3dotsb
)) = paramsb
in
122 let iihas3dotsx = iihas3dotsa
in
124 (ba
=:= bb
&& List.length tsa
=|= List.length tsb
) >&&>
125 fullType returna returnb
>>= (fun returnx
->
127 Common.zip tsa tsb
+> List.fold_left
128 (fun acc
((parama
,iia
),(paramb
,iib
))->
132 let {p_register
= (ba
,iiba
); p_namei
= saopt
; p_type
= ta
} =
134 let {p_register
= (bb
,iibb
); p_namei
= sbopt
; p_type
= tb
} =
143 (* todo? iso on name or argument ? *)
144 (ba
=:= bb
&& same_s saopt sbopt
) >&&>
145 fullType ta tb
>>= (fun tx
->
146 let paramx = { p_register
= (bx, iibx);
149 return ((paramx,iix)::xs
)
154 let paramsx = (List.rev tsx
, (bx, iihas3dotsx)) in
155 return (FunctionType
(returnx
, paramsx), iix)
158 | Enum
(saopt
, enuma
), Enum
(sbopt
, enumb
) ->
160 List.length enuma
=|= List.length enumb
&&
161 Common.zip enuma enumb
+> List.for_all
(fun
162 (((namesa
,eopta
), iicommaa
), ((namesb
,eoptb
),iicommab
))
164 let sa = str_of_name namesa
in
165 let sb = str_of_name namesb
in
167 (* todo ? eopta and b can have some info so ok to use =*= ? *)
171 return (Enum
(saopt
, enuma
), iix)
173 | EnumName
sa, EnumName
sb -> sa =$
= sb >&&> return (EnumName
sa, iix)
175 | ParenType a
, ParenType b
->
177 fullType a b
>>= (fun x
->
178 return (ParenType x
, iix)
181 | TypeOfExpr
ea, TypeOfExpr
eb ->
182 let ea = Lib_parsing_c.al_expr
ea in
183 let eb = Lib_parsing_c.al_expr
eb in
184 ea =*= eb >&&> return (TypeOfExpr
ea, iix)
186 | TypeOfType a
, TypeOfType b
->
187 fullType a b
>>= (fun x
-> return (TypeOfType x
, iix))
189 (* | TypeOfType a, b ->
194 | StructUnion
(sua
, saopt
, sta
), StructUnion
(sub
, sbopt
, stb
) ->
195 (sua
=*= sub
&& saopt
=*= sbopt
&& List.length sta
=|= List.length stb
)
197 Common.zip sta stb
+> List.fold_left
198 (fun acc
((fielda
), (fieldb
)) ->
200 match fielda
, fieldb
with
201 | EmptyField iia
, EmptyField iib
->
203 return ((EmptyField
iix)::xs
)
205 | DeclarationField
(FieldDeclList
(fa
, iipta
)),
206 DeclarationField
(FieldDeclList
(fb
, iiptb
)) ->
207 let iipt = iipta
in (* TODO ?*)
208 (List.length fa
=|= List.length fb
) >&&>
210 Common.zip fa fb
+> List.fold_left
211 (fun acc2
((fielda
,iia
),(fieldb
,iib
))->
214 match fielda
, fieldb
with
215 | Simple
(nameaopt
, ta
), Simple
(namebopt
, tb
) ->
218 same_s nameaopt namebopt
>&&>
219 fullType ta tb
>>= (fun tx
->
220 return (((Simple
(nameaopt
, tx
)), iix)::xs
)
223 | BitField
(nameopta
, ta
, infoa
, ea),
224 BitField
(nameoptb
, tb
, infob
, eb) ->
226 (same_s nameopta nameoptb
&& ea =*= eb) >&&>
227 fullType ta tb
>>= (fun tx
->
228 return (((BitField
(nameopta
,tx
,infox,ea)), iix)::xs
)
234 return (((DeclarationField
235 (FieldDeclList
(List.rev fx
,iipt))))::xs
)
243 return (StructUnion
(sua
, saopt
, List.rev stx
), iix)
249 * subtil: in the return must put iia, not iix, and in following case
250 * must put iib and not iix, because we want the token corresponding
253 | TypeName
(name
, Some a
), _
->
254 fullType a
(Ast_c.nQ
, tyb
) >>= (fun x
->
255 return (TypeName
(name
, Some x
), iia
)
258 | _
, TypeName
(name
, Some b
) ->
259 fullType b
(Ast_c.nQ
, tya
) >>= (fun x
->
260 return (TypeName
(name
, Some x
), iib
) (* subtil: *)
271 type 'a tout
= 'a
option
273 type 'a matcher
= 'a
-> 'a
-> tin
-> 'a tout
275 let return x
= fun tin
-> Some x
276 let fail = fun tin
-> None
278 let (>>=) m f
= fun tin
->
283 let (>&&>) b m
= fun tin
->
289 module EQ
= C_VS_C
(XEQ
)
292 let eq_type2 a b
= EQ.fullType a b
() <> None
293 let merge_type2 a b
= Common.some
(EQ.fullType a b
())
296 Common.profile_code
"C_vs_c" (fun () -> eq_type2 a b
)
299 Common.profile_code
"C_vs_c" (fun () -> merge_type2 a b
)