diff options
Diffstat (limited to 'ocaml-binary-annot/parsing/linenum.mll')
| -rw-r--r-- | ocaml-binary-annot/parsing/linenum.mll | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/ocaml-binary-annot/parsing/linenum.mll b/ocaml-binary-annot/parsing/linenum.mll new file mode 100644 index 0000000000..91e71e972c --- /dev/null +++ b/ocaml-binary-annot/parsing/linenum.mll @@ -0,0 +1,74 @@ +(***********************************************************************) +(* *) +(* Objective Caml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1997 Institut National de Recherche en Informatique et *) +(* en Automatique. All rights reserved. This file is distributed *) +(* under the terms of the Q Public License version 1.0. *) +(* *) +(***********************************************************************) + +(* $Id$ *) + +(* An auxiliary lexer for determining the line number corresponding to + a file position, honoring the directives # linenum "filename" *) + +{ +let filename = ref "" +let linenum = ref 0 +let linebeg = ref 0 + +let parse_sharp_line s = + try + (* Update the line number and file name *) + let l1 = ref 0 in + while let c = s.[!l1] in c < '0' || c > '9' do incr l1 done; + let l2 = ref (!l1 + 1) in + while let c = s.[!l2] in c >= '0' && c <= '9' do incr l2 done; + linenum := int_of_string(String.sub s !l1 (!l2 - !l1)); + let f1 = ref (!l2 + 1) in + while !f1 < String.length s && s.[!f1] <> '"' do incr f1 done; + let f2 = ref (!f1 + 1) in + while !f2 < String.length s && s.[!f2] <> '"' do incr f2 done; + if !f1 < String.length s then + filename := String.sub s (!f1 + 1) (!f2 - !f1 - 1) + with Failure _ | Invalid_argument _ -> + Misc.fatal_error "Linenum.parse_sharp_line" +} + +rule skip_line = parse + "#" [' ' '\t']* ['0'-'9']+ [' ' '\t']* + ("\"" [^ '\n' '\r' '"' (* '"' *) ] * "\"")? + [^ '\n' '\r'] * + ('\n' | '\r' | "\r\n") + { parse_sharp_line(Lexing.lexeme lexbuf); + linebeg := Lexing.lexeme_start lexbuf; + Lexing.lexeme_end lexbuf } + | [^ '\n' '\r'] * + ('\n' | '\r' | "\r\n") + { incr linenum; + linebeg := Lexing.lexeme_start lexbuf; + Lexing.lexeme_end lexbuf } + | [^ '\n' '\r'] * eof + { incr linenum; + linebeg := Lexing.lexeme_start lexbuf; + raise End_of_file } + +{ + +let for_position file loc = + let ic = open_in_bin file in + let lb = Lexing.from_channel ic in + filename := file; + linenum := 1; + linebeg := 0; + begin try + while skip_line lb <= loc do () done + with End_of_file -> () + end; + close_in ic; + (!filename, !linenum - 1, !linebeg) + +} |
