(* Memory info for virtual domains. (C) Copyright 2008 Richard W.M. Jones, Red Hat Inc. http://libvirt.org/ This program 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 2 of the License, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *) (* This program takes the kernel database (in kernels/ in toplevel directory) and generates parsing code for the various structures in the kernel that we are interested in. The output programs -- *.ml, *.mli files of generated code -- go into lib/ at the toplevel, eg. lib/kernel_task_struct.ml The stuff at the top of this file determine what structures and fields we try to parse. *) let what = [ "task_struct", ( "struct task_struct", [ "state"; "prio"; "normal_prio"; "static_prio"; "tasks"; "comm"] ); ] open ExtList open ExtString open Printf let (//) = Filename.concat let () = let args = Array.to_list Sys.argv in let kernelsdir, outputdir = match args with | [_;kd;od] -> kd,od | _ -> let arg0 = Filename.basename Sys.executable_name in eprintf "%s - Turn kernels database into code modules. Usage: %s Example (from toplevel of virt-mem source tree): %s kernels/ lib/ " arg0 arg0 arg0; exit 2 in (* Get the *.info files from the kernels database. *) let infos = Sys.readdir kernelsdir in let infos = Array.to_list infos in let infos = List.filter (fun name -> String.ends_with name ".info") infos in let infos = List.map ((//) kernelsdir) infos in (* Regular expressions. We really really should use ocaml-mikmatch ... *) let re_oldformat = Pcre.regexp "^RPM: \\d+: \\(build \\d+\\) ([-\\w]+) ([\\w.]+) ([\\w.]+) \\(.*?\\) (\\w+)" in let re_keyvalue = Pcre.regexp "^(\\w+): (.*)" in (* Parse in the *.info files. These have historically had a few different * formats that we need to support. *) let infos = List.map ( fun filename -> (* Get the basename (for getting the .data file later on). *) let basename = Filename.chop_suffix filename ".info" in let chan = open_in filename in let line = input_line chan in let name, version = if Pcre.pmatch ~rex:re_oldformat line then ( (* If the file starts with "RPM: \d+: ..." then it's the original * format. Everything in one line. *) let subs = Pcre.exec ~rex:re_oldformat line in let name = Pcre.get_substring subs 1 in let version = Pcre.get_substring subs 2 in let release = Pcre.get_substring subs 3 in let arch = Pcre.get_substring subs 4 in close_in chan; name, sprintf "%s-%s.%s" version release arch ) else ( (* New-style "key: value" entries, up to end of file or the first * blank line. *) let name, version, release, arch = ref "", ref "", ref "", ref "" in let rec loop line = try let subs = Pcre.exec ~rex:re_keyvalue line in let key = Pcre.get_substring subs 1 in let value = Pcre.get_substring subs 2 in if key = "Name" then name := value else if key = "Version" then version := value else if key = "Release" then release := value else if key = "Architecture" then arch := value; let line = input_line chan in loop line with Not_found | End_of_file -> close_in chan in loop line; let name, version, release, arch = !name, !version, !release, !arch in if name = "" || version = "" || release = "" || arch = "" then failwith (sprintf "%s: missing Name, Version, Release or Architecture key" filename); name, sprintf "%s-%s.%s" version release arch ) in printf "%s -> %s, %s\n" basename name version; (basename, name, version) ) infos in ()