2

I'm developping a plugin in frama-c and I want to get line number in source code. In this little script for example:

open Cil_types
open Cil_types
open Cil_datatype
let print_loc kf =             
let locals = Kernel_function.get_locals kf in 
   List.iter (fun vi -> 
      let line =  Cil_datatype.Location.pretty_line Format.sprintf "%a" Printer.pp_location vi.vdecl in
      Format.printf "Line %a: %a %s@." 
      Printer.pp_location vi.vdecl Printer.pp_typ vi.vtype vi.vname
   ) locals

let () =
Db.Main.extend (fun () ->
  Format.printf "Printing all local vars...@.";
  let fun_name = "main" in
  let kf = Globals.Functions.find_by_name fun_name in
  print_loc kf;
  Format.printf "done!@.")

Printer.pp_location print the full path. I want just the line number.

I found pretty_line in Cil_datatype.Location module and tried to use it but I can not. I'm getting compile errors and I have not found an example of using this function in Frama-C sources.

I tried this,

let print_loc kf =             
let locals = Kernel_function.get_locals kf in 
List.iter (fun vi -> 
let line =  Cil_datatype.Location.pretty_line Format.sprintf "%a" Printer.pp_location vi.vdecl in
Format.printf "Line %d: %a %s@." line Printer.pp_typ vi.vtype vi.vname) locals

And I got this error message

Error: This function has type Format.formatter -> Cil_datatype.Location.t -> unit It is applied to too many arguments; maybe you forgot a `;'.

I tried several combinations, but in any case, either I get the previous error message or I get this message:

Error: This expression has type Format.formatter -> Cil_types.location -> unit but an expression was expected of type unit -> 'a -> string Type Format.formatter is not compatible with type unit

Can I get the information about line number otherwise? Or How can I properly use Cil_datatype.Location.pretty_line ?

Thanks

R. Fomba
  • 79
  • 8

2 Answers2

4

octachtron's answer summarizes nicely how to use pretty_line with a format string. However, if you want to use the line number as an integer (not necessarily to print it with %d), Cil_datatype.Location.t is a concrete type, more precisely an alias to Cil_types.location, which is itself a pair of Lexing.location. Hence, for retrieving the line where the location starts, you can simply do

...
let line = (fst vi.vdecl).Lexing.pos_lnum in 
...
Virgile
  • 9,724
  • 18
  • 42
  • Thanks. I needed to generate the line number as an integer so `(fst vi.vdecl) .Lexing.pos_lnum` is exactly what I needed. – R. Fomba Mar 13 '18 at 13:16
  • @R.Fomba You're welcome. In this case, don't hesitate to [mark this answer as accepted](https://stackoverflow.com/help/someone-answers). – Virgile Mar 13 '18 at 14:43
3

Functions with type Format.formatter -> 'a -> unit are designed to be used in conjunction of the %a specififier, for instance with a formatter ppf and a location loc:

let () = Format.fprintf ppf "%a" Cil_datatype.Location.pretty_line loc

A particularity is that if you want to generate a string, you should use asprintf rather than sprintf:

let s = Format.asprintf "%a" Cil_datatype.Location.pretty_line loc
octachron
  • 17,178
  • 2
  • 16
  • 23
  • 1
    In addition, you might want to show how `pretty_line` can be used directly in the final `printf`: `Format.printf "Line %a: %a %s@." Cil_datatype.Location.pretty_line vi.vdecl Printer.pp_typ vi.vtype vi.vname` – Virgile Mar 12 '18 at 13:29