summaryrefslogtreecommitdiffstats
path: root/camlp4/ocaml_src/lib/stdpp.ml
diff options
context:
space:
mode:
Diffstat (limited to 'camlp4/ocaml_src/lib/stdpp.ml')
-rw-r--r--camlp4/ocaml_src/lib/stdpp.ml78
1 files changed, 66 insertions, 12 deletions
diff --git a/camlp4/ocaml_src/lib/stdpp.ml b/camlp4/ocaml_src/lib/stdpp.ml
index 0830e6842..d91ee78c0 100644
--- a/camlp4/ocaml_src/lib/stdpp.ml
+++ b/camlp4/ocaml_src/lib/stdpp.ml
@@ -23,23 +23,77 @@ let raise_with_loc loc exc =
let line_of_loc fname (bp, ep) =
try
let ic = open_in_bin fname in
- let rec loop lin col cnt =
- if cnt < bp then
- let (lin, col) =
- match input_char ic with
- '\n' -> lin + 1, 0
- | _ -> lin, col + 1
- in
- loop lin col (cnt + 1)
- else lin, col, col + ep - bp
+ let strm = Stream.of_channel ic in
+ let rec loop fname lin =
+ let rec not_a_line_dir col (strm__ : _ Stream.t) =
+ let cnt = Stream.count strm__ in
+ match Stream.peek strm__ with
+ Some c ->
+ Stream.junk strm__;
+ let s = strm__ in
+ if cnt < bp then
+ if c = '\n' then loop fname (lin + 1)
+ else not_a_line_dir (col + 1) s
+ else let col = col - (cnt - bp) in fname, lin, col, col + ep - bp
+ | _ -> raise Stream.Failure
+ in
+ let rec a_line_dir str n col (strm__ : _ Stream.t) =
+ match Stream.peek strm__ with
+ Some '\n' -> Stream.junk strm__; loop str n
+ | Some _ -> Stream.junk strm__; a_line_dir str n (col + 1) strm__
+ | _ -> raise Stream.Failure
+ in
+ let rec spaces col (strm__ : _ Stream.t) =
+ match Stream.peek strm__ with
+ Some ' ' -> Stream.junk strm__; spaces (col + 1) strm__
+ | _ -> col
+ in
+ let rec check_string str n col (strm__ : _ Stream.t) =
+ match Stream.peek strm__ with
+ Some '\"' ->
+ Stream.junk strm__;
+ let col =
+ try spaces (col + 1) strm__ with
+ Stream.Failure -> raise (Stream.Error "")
+ in
+ a_line_dir str n col strm__
+ | Some c when c <> '\n' ->
+ Stream.junk strm__;
+ check_string (str ^ String.make 1 c) n (col + 1) strm__
+ | _ -> not_a_line_dir col strm__
+ in
+ let check_quote n col (strm__ : _ Stream.t) =
+ match Stream.peek strm__ with
+ Some '\"' -> Stream.junk strm__; check_string "" n (col + 1) strm__
+ | _ -> not_a_line_dir col strm__
+ in
+ let rec check_num n col (strm__ : _ Stream.t) =
+ match Stream.peek strm__ with
+ Some ('0'..'9' as c) ->
+ Stream.junk strm__;
+ check_num (10 * n + Char.code c - Char.code '0') (col + 1) strm__
+ | _ -> let col = spaces col strm__ in check_quote n col strm__
+ in
+ let begin_line (strm__ : _ Stream.t) =
+ match Stream.peek strm__ with
+ Some '#' ->
+ Stream.junk strm__;
+ let col =
+ try spaces 1 strm__ with
+ Stream.Failure -> raise (Stream.Error "")
+ in
+ check_num 0 col strm__
+ | _ -> not_a_line_dir 0 strm__
+ in
+ begin_line strm
in
let r =
- try loop 1 0 0 with
- End_of_file -> 1, bp, ep
+ try loop fname 1 with
+ Stream.Failure -> fname, 1, bp, ep
in
close_in ic; r
with
- Sys_error _ -> 1, bp, ep
+ Sys_error _ -> fname, 1, bp, ep
;;
let loc_name = ref "loc";;