1996-11-29 08:55:09 -08:00
|
|
|
(***********************************************************************)
|
|
|
|
(* *)
|
2011-07-27 07:17:02 -07:00
|
|
|
(* OCaml *)
|
1996-11-29 08:55:09 -08:00
|
|
|
(* *)
|
|
|
|
(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *)
|
2011-07-27 07:17:02 -07:00
|
|
|
(* OCaml port by John Malecki and Xavier Leroy *)
|
1996-11-29 08:55:09 -08:00
|
|
|
(* *)
|
|
|
|
(* Copyright 1996 Institut National de Recherche en Informatique et *)
|
1999-11-17 10:59:06 -08:00
|
|
|
(* en Automatique. All rights reserved. This file is distributed *)
|
|
|
|
(* under the terms of the Q Public License version 1.0. *)
|
1996-11-29 08:55:09 -08:00
|
|
|
(* *)
|
|
|
|
(***********************************************************************)
|
|
|
|
|
|
|
|
(************************ Source management ****************************)
|
|
|
|
|
|
|
|
open Misc
|
|
|
|
open Primitives
|
|
|
|
|
2006-12-09 05:49:10 -08:00
|
|
|
let source_extensions = [".ml"]
|
|
|
|
|
1996-11-29 08:55:09 -08:00
|
|
|
(*** Conversion function. ***)
|
|
|
|
|
2006-12-09 05:49:10 -08:00
|
|
|
let source_of_module pos mdle =
|
2009-05-20 04:52:42 -07:00
|
|
|
let is_submodule m m' =
|
|
|
|
let len' = String.length m' in
|
|
|
|
try
|
|
|
|
(String.sub m 0 len') = m' && (String.get m len') = '.'
|
|
|
|
with
|
2012-05-30 07:52:37 -07:00
|
|
|
Invalid_argument _ -> false in
|
2009-05-20 04:52:42 -07:00
|
|
|
let path =
|
|
|
|
Hashtbl.fold
|
|
|
|
(fun mdl dirs acc ->
|
|
|
|
if is_submodule mdle mdl then
|
|
|
|
dirs
|
|
|
|
else
|
|
|
|
acc)
|
|
|
|
Debugger_config.load_path_for
|
|
|
|
!Config.load_path in
|
2006-12-09 05:49:10 -08:00
|
|
|
let fname = pos.Lexing.pos_fname in
|
2012-05-30 07:52:37 -07:00
|
|
|
if fname = "" then
|
|
|
|
let innermost_module =
|
|
|
|
try
|
|
|
|
let dot_index = String.rindex mdle '.' in
|
2013-03-09 14:38:52 -08:00
|
|
|
String.sub mdle (succ dot_index) (pred (String.length mdle - dot_index))
|
2012-05-30 07:52:37 -07:00
|
|
|
with Not_found -> mdle in
|
|
|
|
let rec loop =
|
|
|
|
function
|
|
|
|
| [] -> raise Not_found
|
|
|
|
| ext :: exts ->
|
|
|
|
try find_in_path_uncap path (innermost_module ^ ext)
|
|
|
|
with Not_found -> loop exts
|
|
|
|
in loop source_extensions
|
2014-10-15 06:34:58 -07:00
|
|
|
else if Filename.is_relative fname then
|
|
|
|
find_in_path_rel path fname
|
|
|
|
else if Sys.file_exists fname then fname
|
|
|
|
else raise Not_found
|
1996-11-29 08:55:09 -08:00
|
|
|
|
|
|
|
(*** Buffer cache ***)
|
|
|
|
|
|
|
|
(* Buffer and cache (to associate lines and positions in the buffer). *)
|
|
|
|
type buffer = string * (int * int) list ref
|
|
|
|
|
|
|
|
let buffer_max_count = ref 10
|
|
|
|
|
|
|
|
let cache_size = 30
|
|
|
|
|
|
|
|
let buffer_list =
|
|
|
|
ref ([] : (string * buffer) list)
|
|
|
|
|
|
|
|
let flush_buffer_list () =
|
|
|
|
buffer_list := []
|
|
|
|
|
2006-12-09 05:49:10 -08:00
|
|
|
let get_buffer pos mdle =
|
1996-11-29 08:55:09 -08:00
|
|
|
try List.assoc mdle !buffer_list with
|
|
|
|
Not_found ->
|
2006-12-09 05:49:10 -08:00
|
|
|
let inchan = open_in_bin (source_of_module pos mdle) in
|
2014-04-29 04:56:17 -07:00
|
|
|
let content = really_input_string inchan (in_channel_length inchan) in
|
2012-02-23 11:54:44 -08:00
|
|
|
let buffer = (content, ref []) in
|
|
|
|
buffer_list :=
|
|
|
|
(list_truncate !buffer_max_count ((mdle, buffer)::!buffer_list));
|
|
|
|
buffer
|
1996-11-29 08:55:09 -08:00
|
|
|
|
|
|
|
let buffer_content =
|
|
|
|
(fst : buffer -> string)
|
|
|
|
|
|
|
|
let buffer_length x =
|
|
|
|
String.length (buffer_content x)
|
|
|
|
|
|
|
|
(*** Position conversions. ***)
|
|
|
|
|
|
|
|
type position = int * int
|
|
|
|
|
|
|
|
(* Insert a new pair (position, line) in the cache of the given buffer. *)
|
|
|
|
let insert_pos buffer ((position, line) as pair) =
|
|
|
|
let rec new_list =
|
|
|
|
function
|
|
|
|
[] ->
|
1997-05-19 08:42:21 -07:00
|
|
|
[(position, line)]
|
1996-11-29 08:55:09 -08:00
|
|
|
| ((pos, lin) as a::l) as l' ->
|
|
|
|
if lin < line then
|
1997-05-19 08:42:21 -07:00
|
|
|
pair::l'
|
|
|
|
else if lin = line then
|
|
|
|
l'
|
|
|
|
else
|
|
|
|
a::(new_list l)
|
1996-11-29 08:55:09 -08:00
|
|
|
in
|
|
|
|
let buffer_cache = snd buffer in
|
|
|
|
buffer_cache := new_list !buffer_cache
|
|
|
|
|
|
|
|
(* Position of the next linefeed after `pos'. *)
|
|
|
|
(* Position just after the buffer end if no linefeed found. *)
|
|
|
|
(* Raise `Out_of_range' if already there. *)
|
|
|
|
let next_linefeed (buffer, _) pos =
|
|
|
|
let len = String.length buffer in
|
|
|
|
if pos >= len then
|
|
|
|
raise Out_of_range
|
|
|
|
else
|
|
|
|
let rec search p =
|
2000-03-07 10:22:19 -08:00
|
|
|
if p = len || String.get buffer p = '\n' then
|
1996-11-29 08:55:09 -08:00
|
|
|
p
|
|
|
|
else
|
1997-05-19 08:42:21 -07:00
|
|
|
search (succ p)
|
1996-11-29 08:55:09 -08:00
|
|
|
in
|
|
|
|
search pos
|
|
|
|
|
|
|
|
(* Go to next line. *)
|
|
|
|
let next_line buffer (pos, line) =
|
|
|
|
(next_linefeed buffer pos + 1, line + 1)
|
|
|
|
|
|
|
|
(* Convert a position in the buffer to a line number. *)
|
|
|
|
let line_of_pos buffer position =
|
|
|
|
let rec find =
|
|
|
|
function
|
2000-03-07 10:22:19 -08:00
|
|
|
| [] ->
|
1997-05-19 08:42:21 -07:00
|
|
|
if position < 0 then
|
|
|
|
raise Out_of_range
|
|
|
|
else
|
|
|
|
(0, 1)
|
1996-11-29 08:55:09 -08:00
|
|
|
| ((pos, line) as pair)::l ->
|
1997-05-19 08:42:21 -07:00
|
|
|
if pos > position then
|
|
|
|
find l
|
|
|
|
else
|
|
|
|
pair
|
1996-11-29 08:55:09 -08:00
|
|
|
and find_line previous =
|
|
|
|
let (pos, line) as next = next_line buffer previous in
|
|
|
|
if pos <= position then
|
1997-05-19 08:42:21 -07:00
|
|
|
find_line next
|
1996-11-29 08:55:09 -08:00
|
|
|
else
|
1997-05-19 08:42:21 -07:00
|
|
|
previous
|
1996-11-29 08:55:09 -08:00
|
|
|
in
|
|
|
|
let result = find_line (find !(snd buffer)) in
|
|
|
|
insert_pos buffer result;
|
|
|
|
result
|
|
|
|
|
|
|
|
(* Convert a line number to a position. *)
|
|
|
|
let pos_of_line buffer line =
|
|
|
|
let rec find =
|
|
|
|
function
|
|
|
|
[] ->
|
|
|
|
if line <= 0 then
|
|
|
|
raise Out_of_range
|
1997-05-19 08:42:21 -07:00
|
|
|
else
|
1996-11-29 08:55:09 -08:00
|
|
|
(0, 1)
|
|
|
|
| ((pos, lin) as pair)::l ->
|
1997-05-19 08:42:21 -07:00
|
|
|
if lin > line then
|
|
|
|
find l
|
|
|
|
else
|
|
|
|
pair
|
1996-11-29 08:55:09 -08:00
|
|
|
and find_pos previous =
|
|
|
|
let (_, lin) as next = next_line buffer previous in
|
|
|
|
if lin <= line then
|
1997-05-19 08:42:21 -07:00
|
|
|
find_pos next
|
1996-11-29 08:55:09 -08:00
|
|
|
else
|
1997-05-19 08:42:21 -07:00
|
|
|
previous
|
1996-11-29 08:55:09 -08:00
|
|
|
in
|
|
|
|
let result = find_pos (find !(snd buffer)) in
|
|
|
|
insert_pos buffer result;
|
|
|
|
result
|
|
|
|
|
|
|
|
(* Convert a coordinate (line / column) into a position. *)
|
|
|
|
(* --- The first line and column are line 1 and column 1. *)
|
|
|
|
let point_of_coord buffer line column =
|
|
|
|
fst (pos_of_line buffer line) + (pred column)
|
2010-01-20 08:26:46 -08:00
|
|
|
|
|
|
|
let start_and_cnum buffer pos =
|
|
|
|
let line_number = pos.Lexing.pos_lnum in
|
|
|
|
let start = point_of_coord buffer line_number 1 in
|
|
|
|
start, start + (pos.Lexing.pos_cnum - pos.Lexing.pos_bol)
|