2012-06-27 18:09:30 +02:00
|
|
|
(***********************************************************************)
|
|
|
|
(* *)
|
|
|
|
(* Heptagon *)
|
|
|
|
(* *)
|
|
|
|
(* Gwenael Delaval, LIG/INRIA, UJF *)
|
|
|
|
(* Leonard Gerard, Parkas, ENS *)
|
|
|
|
(* Adrien Guatto, Parkas, ENS *)
|
|
|
|
(* Cedric Pasteur, Parkas, ENS *)
|
|
|
|
(* *)
|
|
|
|
(* Copyright 2012 ENS, INRIA, UJF *)
|
|
|
|
(* *)
|
|
|
|
(* This file is part of the Heptagon compiler. *)
|
|
|
|
(* *)
|
|
|
|
(* Heptagon is free software: you can redistribute it and/or modify it *)
|
|
|
|
(* under the terms of the GNU General Public License as published by *)
|
|
|
|
(* the Free Software Foundation, either version 3 of the License, or *)
|
|
|
|
(* (at your option) any later version. *)
|
|
|
|
(* *)
|
|
|
|
(* Heptagon is distributed in the hope that it will be useful, *)
|
|
|
|
(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
|
|
|
|
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
|
|
|
|
(* GNU General Public License for more details. *)
|
|
|
|
(* *)
|
|
|
|
(* You should have received a copy of the GNU General Public License *)
|
|
|
|
(* along with Heptagon. If not, see <http://www.gnu.org/licenses/> *)
|
|
|
|
(* *)
|
|
|
|
(***********************************************************************)
|
2010-06-15 10:49:03 +02:00
|
|
|
(* Printing a location in the source program *)
|
2010-07-16 17:33:14 +02:00
|
|
|
(* inspired from the source of the Caml Light 0.73 compiler *)
|
2010-06-15 10:49:03 +02:00
|
|
|
|
|
|
|
open Lexing
|
|
|
|
open Parsing
|
2010-08-24 17:23:50 +02:00
|
|
|
open Format
|
2010-06-15 10:49:03 +02:00
|
|
|
|
|
|
|
(* two important global variables: [input_name] and [input_chan] *)
|
|
|
|
type location =
|
2010-07-16 17:33:14 +02:00
|
|
|
Loc of position (* Position of the first character *)
|
|
|
|
* position (* Position of the next character following the last one *)
|
2010-06-15 10:49:03 +02:00
|
|
|
|
|
|
|
|
|
|
|
let input_name = ref "" (* Input file name. *)
|
|
|
|
|
2010-07-16 17:33:14 +02:00
|
|
|
let input_chan = ref stdin (* The channel opened on the input. *)
|
2010-06-15 10:49:03 +02:00
|
|
|
|
|
|
|
let initialize iname ic =
|
|
|
|
input_name := iname;
|
|
|
|
input_chan := ic
|
|
|
|
|
|
|
|
|
2010-07-16 17:33:14 +02:00
|
|
|
let no_location = Loc (dummy_pos, dummy_pos)
|
2010-06-15 10:49:03 +02:00
|
|
|
|
|
|
|
let error_prompt = ">"
|
|
|
|
|
|
|
|
|
2010-07-16 17:33:14 +02:00
|
|
|
(** Prints [n] times char [c] on [oc]. *)
|
2010-08-24 17:23:50 +02:00
|
|
|
let prints_n_chars ff n c = for i = 1 to n do pp_print_char ff c done
|
2010-06-15 10:49:03 +02:00
|
|
|
|
2010-07-16 17:33:14 +02:00
|
|
|
(** Prints out to [oc] a line designed to be printed under [line] from file [ic]
|
|
|
|
underlining from char [first] to char [last] with char [ch].
|
|
|
|
[line] is the index of the first char of line. *)
|
2010-08-24 17:23:50 +02:00
|
|
|
let underline_line ic ff ch line first last =
|
2010-07-16 17:33:14 +02:00
|
|
|
let c = ref ' '
|
|
|
|
and f = ref first
|
|
|
|
and l = ref (last-first) in
|
|
|
|
( try
|
|
|
|
seek_in ic line;
|
2010-08-24 17:23:50 +02:00
|
|
|
pp_print_string ff error_prompt;
|
2010-07-16 17:33:14 +02:00
|
|
|
while c := input_char ic; !c != '\n' do
|
|
|
|
if !f > 0 then begin
|
|
|
|
f := !f - 1;
|
2010-08-24 17:23:50 +02:00
|
|
|
pp_print_char ff (if !c == '\t' then !c else ' ')
|
2010-07-16 17:33:14 +02:00
|
|
|
end
|
|
|
|
else if !l > 0 then begin
|
|
|
|
l := !l - 1;
|
2010-08-24 17:23:50 +02:00
|
|
|
pp_print_char ff (if !c == '\t' then !c else ch)
|
2010-07-16 17:33:14 +02:00
|
|
|
end
|
|
|
|
else ()
|
2010-06-15 10:49:03 +02:00
|
|
|
done
|
2010-07-16 17:33:14 +02:00
|
|
|
with End_of_file ->
|
2010-08-24 17:23:50 +02:00
|
|
|
if !f = 0 && !l > 0 then prints_n_chars ff 5 ch )
|
2010-07-16 17:33:14 +02:00
|
|
|
|
|
|
|
|
2010-08-24 17:23:50 +02:00
|
|
|
let copy_lines nl ic ff prompt =
|
2010-07-16 17:33:14 +02:00
|
|
|
for i = 1 to nl do
|
2010-08-24 17:23:50 +02:00
|
|
|
pp_print_string ff prompt;
|
|
|
|
(try pp_print_string ff (input_line ic)
|
|
|
|
with End_of_file -> pp_print_string ff "<EOF>");
|
2010-10-08 14:34:31 +02:00
|
|
|
fprintf ff "@\n"
|
2010-07-16 17:33:14 +02:00
|
|
|
done
|
|
|
|
|
2010-08-24 17:23:50 +02:00
|
|
|
let copy_chunk p1 p2 ic ff =
|
|
|
|
try for i = p1 to p2 - 1 do pp_print_char ff (input_char ic) done
|
|
|
|
with End_of_file -> pp_print_string ff "<EOF>"
|
2010-07-16 17:33:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let skip_lines n ic =
|
|
|
|
try for i = 1 to n do
|
|
|
|
let _ = input_line ic in ()
|
2010-06-15 10:49:03 +02:00
|
|
|
done
|
|
|
|
with End_of_file -> ()
|
|
|
|
|
|
|
|
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-08-24 17:23:50 +02:00
|
|
|
let print_location ff (Loc(p1,p2)) =
|
2010-07-16 17:33:14 +02:00
|
|
|
let n1 = p1.pos_cnum - p1.pos_bol in (* character number *)
|
|
|
|
let n2 = p2.pos_cnum - p2.pos_bol in
|
|
|
|
let np1 = p1.pos_cnum in (* character position *)
|
|
|
|
let np2 = p2.pos_cnum in
|
|
|
|
let l1 = p1.pos_lnum in (* line number *)
|
|
|
|
let l2 = p2.pos_lnum in
|
|
|
|
let lp1 = p1.pos_bol in (* line position *)
|
|
|
|
let lp2 = p2.pos_bol in
|
|
|
|
let f1 = p1.pos_fname in (* file name *)
|
|
|
|
let f2 = p2.pos_fname in
|
|
|
|
|
|
|
|
if f1 != f2 then (* Strange case *)
|
2010-08-24 17:23:50 +02:00
|
|
|
fprintf ff
|
2010-09-09 00:35:06 +02:00
|
|
|
"File \"%s\" line %d, character %d, to file \"%s\" line %d, character %d@."
|
2010-07-16 17:33:14 +02:00
|
|
|
f1 l1 n1 f2 l2 n2
|
2010-06-15 10:49:03 +02:00
|
|
|
|
2010-09-09 00:35:06 +02:00
|
|
|
else begin (* Same file *)
|
2010-07-16 17:33:14 +02:00
|
|
|
if l2 > l1 then
|
2010-08-24 17:23:50 +02:00
|
|
|
fprintf ff
|
|
|
|
"File \"%s\", line %d-%d, characters %d-%d:@\n" f1 l1 l2 n1 n2
|
2010-07-16 17:33:14 +02:00
|
|
|
else
|
2010-08-24 17:23:50 +02:00
|
|
|
fprintf ff "File \"%s\", line %d, characters %d-%d:@\n" f1 l1 n1 n2;
|
2010-07-16 17:33:14 +02:00
|
|
|
(* Output source code *)
|
2010-07-27 13:31:13 +02:00
|
|
|
try
|
|
|
|
let ic = open_in f1 in
|
|
|
|
|
|
|
|
if l1 == l2 then (
|
|
|
|
(* Only one line : copy full line and underline *)
|
|
|
|
seek_in ic lp1;
|
2010-08-24 17:23:50 +02:00
|
|
|
copy_lines 1 ic ff ">";
|
|
|
|
underline_line ic ff '^' lp1 n1 n2 )
|
2010-07-16 17:33:14 +02:00
|
|
|
else (
|
2010-08-24 17:23:50 +02:00
|
|
|
underline_line ic ff '.' lp1 0 n1; (* dots until n1 *)
|
2010-07-27 13:31:13 +02:00
|
|
|
seek_in ic np1;
|
|
|
|
(* copy the end of the line l1 after the dots *)
|
2010-08-24 17:23:50 +02:00
|
|
|
copy_lines 1 ic ff "";
|
2010-07-27 13:31:13 +02:00
|
|
|
if l2 - l1 <= 8 then
|
|
|
|
(* copy the 6 or less middle lines *)
|
2010-08-24 17:23:50 +02:00
|
|
|
copy_lines (l2-l1-1) ic ff ">"
|
2010-07-27 13:31:13 +02:00
|
|
|
else (
|
|
|
|
(* sum up the middle lines to 6 *)
|
2010-08-24 17:23:50 +02:00
|
|
|
copy_lines 3 ic ff ">";
|
2010-10-08 14:34:31 +02:00
|
|
|
fprintf ff "..........@\n";
|
2010-07-27 13:31:13 +02:00
|
|
|
skip_lines (l2-l1-7) ic; (* skip middle lines *)
|
2010-08-24 17:23:50 +02:00
|
|
|
copy_lines 3 ic ff ">"
|
2010-07-27 13:31:13 +02:00
|
|
|
);
|
2010-10-08 14:34:31 +02:00
|
|
|
fprintf ff ">";
|
2010-08-24 17:23:50 +02:00
|
|
|
copy_chunk lp2 np2 ic ff; (* copy interesting begining of l2 *)
|
2010-07-27 13:31:13 +02:00
|
|
|
)
|
|
|
|
with Sys_error _ -> ();
|
2010-07-16 17:33:14 +02:00
|
|
|
end;
|
2010-09-01 13:31:28 +02:00
|
|
|
fprintf ff "@."
|