let rewrite_cursor_pointers file =
  (* Variables to communicate between the collecting visitor and
   * the rewriting one. *)

  let cursor_to_base = VarinfoHashtbl.create 0 in
  let formal_to_base = VarinfoHashtbl.create 0 in
  let assigned_vars = ref VarinfoSet.empty in
  let ignore_vars = ref VarinfoSet.empty in

  (* Collect the cursor variables and their base *)
  let visitor =
    new collectCursorPointers
      cursor_to_base formal_to_base assigned_vars ignore_vars
  in
  visit_until_convergence visitor file;

  (* Normalize the information *)
  let rec transitive_basis v =
    try transitive_basis (VarinfoHashtbl.find formal_to_base v)
    with Not_found -> v
  in
  VarinfoHashtbl.iter
    (fun v _ -> VarinfoHashtbl.add formal_to_base v (transitive_basis v))
    formal_to_base;
  VarinfoSet.iter
    (fun v -> VarinfoHashtbl.remove cursor_to_base v) !ignore_vars;
  VarinfoHashtbl.iter
    (fun v vb -> if VarinfoSet.mem vb !ignore_vars then
      VarinfoHashtbl.remove cursor_to_base v) cursor_to_base;
  VarinfoHashtbl.iter
    (fun v vb -> if VarinfoSet.mem vb !ignore_vars then
      VarinfoHashtbl.remove formal_to_base v) formal_to_base;

  (* Rewrite cursor variables as offsets from their base variable *)
  let visitor =
    new rewriteCursorPointers
      cursor_to_base formal_to_base !assigned_vars
  in
  visitFramacFile (visit_and_push_statements_visitor visitor) file