let locate ?alarm ?pos e =
let rec dopos ~toplevel e =
let pos = match pos with
| None -> e#pos
| Some pos ->
if is_unknown_location e#pos then pos else e#pos
in
let lab = match alarm with
| None ->
reg_pos pos
| Some Alarms.Division_alarm ->
reg_pos ~kind:Output.DivByZero pos
| Some Alarms.Memory_alarm | Some Alarms.Index_alarm ->
reg_pos ~kind:Output.PointerDeref pos
| Some (Alarms.Shift_alarm|Alarms.Signed_overflow_alarm) ->
reg_pos ~kind:Output.ArithOverflow pos
| Some Alarms.Pointer_compare_alarm
| Some Alarms.Using_nan_or_infinite_alarm
| Some Alarms.Result_is_nan_or_infinite_alarm ->
reg_pos pos
| Some Alarms.Separation_alarm -> reg_pos pos
| Some Alarms.Other_alarm -> reg_pos pos
in
let e = match e#node with
| JCPEbinary(e1,`Bland,e2) ->
begin match e1#node,e2#node with
| JCPElabel _,JCPElabel _ -> e
| JCPElabel _,_ ->
let e2 = dopos ~toplevel:false e2 in
mkexpr (JCPEbinary(e1,`Bland,e2)) pos
| _,JCPElabel _ ->
let e1 = dopos ~toplevel:false e1 in
mkexpr (JCPEbinary(e1,`Bland,e2)) pos
| _,_ ->
let e1 = dopos ~toplevel:false e1 in
let e2 = dopos ~toplevel:false e2 in
mkexpr (JCPEbinary(e1,`Bland,e2)) pos
end
| _ -> e
in
match e#node with
| JCPEbinary(_e1,`Bland,_e2) when not toplevel -> e
| _ ->
mkexpr (JCPElabel(lab,e)) pos
in
dopos ~toplevel:true e