(**************************************************************************) (* *) (* OCaml *) (* *) (* Luc Maranget, projet Moscova, *) (* INRIA Rocquencourt *) (* *) (* Copyright 2002 Institut National de Recherche en Informatique et *) (* en Automatique. *) (* *) (* All rights reserved. This file is distributed under the terms of *) (* the GNU Lesser General Public License version 2.1, with the *) (* special exception on linking described in the file LICENSE. *) (* *) (**************************************************************************) open Printf open Syntax open Lexgen (* To copy the ML code fragments *) type line_tracker = { file : string; oc : out_channel; ic : in_channel; mutable cur_line : int; };; let open_tracker file oc = { file = file; oc = oc; ic = open_in_bin file; cur_line = 1; };; let close_tracker tr = close_in_noerr tr.ic;; let update_tracker tr = fprintf tr.oc "\n"; flush tr.oc; let cr_seen = ref false in try while true do match input_char tr.ic with | '\010' when not !cr_seen -> tr.cur_line <- tr.cur_line + 1; | '\013' -> cr_seen := true; tr.cur_line <- tr.cur_line + 1; | _ -> cr_seen := false; done with End_of_file -> fprintf tr.oc "# %d \"%s\"\n" (tr.cur_line+1) tr.file; ;; let copy_buffer = Bytes.create 1024 let copy_chars_unix ic oc start stop = let n = ref (stop - start) in while !n > 0 do let m = input ic copy_buffer 0 (min !n 1024) in output oc copy_buffer 0 m; n := !n - m done let copy_chars_win32 ic oc start stop = for _i = start to stop - 1 do let c = input_char ic in if c <> '\r' then output_char oc c done let copy_chars = match Sys.os_type with "Win32" | "Cygwin" -> copy_chars_win32 | _ -> copy_chars_unix let copy_chunk ic oc trl loc add_parens = if loc.start_pos < loc.end_pos || add_parens then begin fprintf oc "# %d \"%s\"\n" loc.start_line loc.loc_file; if add_parens then begin for _i = 1 to loc.start_col - 1 do output_char oc ' ' done; output_char oc '('; end else begin for _i = 1 to loc.start_col do output_char oc ' ' done; end; seek_in ic loc.start_pos; copy_chars ic oc loc.start_pos loc.end_pos; if add_parens then output_char oc ')'; update_tracker trl; end (* Various memory actions *) let output_mem_access oc i = fprintf oc "lexbuf.Lexing.lex_mem.(%d)" i let output_memory_actions pref oc = function | [] -> () | mvs -> output_string oc "(* " ; fprintf oc "L=%d " (List.length mvs) ; List.iter (fun mv -> match mv with | Copy (tgt, src) -> fprintf oc "[%d] <- [%d] ;" tgt src | Set tgt -> fprintf oc "[%d] <- p ; " tgt) mvs ; output_string oc " *)\n" ; List.iter (fun mv -> match mv with | Copy (tgt, src) -> fprintf oc "%s%a <- %a ;\n" pref output_mem_access tgt output_mem_access src | Set tgt -> fprintf oc "%s%a <- lexbuf.Lexing.lex_curr_pos ;\n" pref output_mem_access tgt) mvs let output_base_mem oc = function | Mem i -> output_mem_access oc i | Start -> fprintf oc "lexbuf.Lexing.lex_start_pos" | End -> fprintf oc "lexbuf.Lexing.lex_curr_pos" let output_tag_access oc = function | Sum (a,0) -> output_base_mem oc a | Sum (a,i) -> fprintf oc "(%a + %d)" output_base_mem a i let output_env ic oc tr env = let pref = ref "let" in match env with | [] -> () | _ -> (* Probably, we are better with variables sorted in apparition order *) let env = List.sort (fun ((_,p1),_) ((_,p2),_) -> Stdlib.compare p1.start_pos p2.start_pos) env in List.iter (fun ((_,pos),v) -> fprintf oc "%s\n" !pref ; copy_chunk ic oc tr pos false ; begin match v with | Ident_string (o,nstart,nend) -> fprintf oc "= Lexing.sub_lexeme%s lexbuf %a %a" (if o then "_opt" else "") output_tag_access nstart output_tag_access nend | Ident_char (o,nstart) -> fprintf oc "= Lexing.sub_lexeme_char%s lexbuf %a" (if o then "_opt" else "") output_tag_access nstart end ; pref := "\nand") env ; fprintf oc " in\n" (* Output the user arguments *) let output_args oc args = List.iter (fun x -> (output_string oc x; output_char oc ' ')) args let output_refill_handler ic oc oci = function | None -> false | Some location -> output_string oc "let __ocaml_lex_refill : \ (Lexing.lexbuf -> 'a) -> (Lexing.lexbuf -> 'a) =\n"; copy_chunk ic oc oci location true; true (* quiet flag *) let quiet_mode = ref false;;