Added Italian, updated Polish PO files.
[virt-mem.git] / extract / codegen / pahole_parser.ml
index f8b5bd1..19cbbf1 100644 (file)
@@ -27,6 +27,7 @@ let (//) = Filename.concat
 type pathname = string
 
 type info = {
+  kv_i : int;
   kernel_version : string;
   arch : string;
   basename : string;
@@ -54,7 +55,7 @@ and f_type =
   | FString of int
 
 let string_of_info i =
-  sprintf "%s: %s %s" i.basename i.kernel_version i.arch
+  sprintf "%s: %s (%d) %s" i.basename i.kernel_version i.kv_i i.arch
 
 let rec string_of_structure s =
   let fields = List.map string_of_field s.struct_fields in
@@ -78,6 +79,10 @@ and string_of_f_type = function
   | FInteger -> "int"
   | FString width -> sprintf "char[%d]" width
 
+let file_exists name =
+  try Unix.access name [Unix.F_OK]; true
+  with Unix.Unix_error _ -> false
+
 (* Regular expressions.  We really really should use ocaml-mikmatch ... *)
 let re_oldformat = Pcre.regexp "^RPM: \\d+: \\(build \\d+\\) ([-\\w]+) ([\\w.]+) ([\\w.]+) \\(.*?\\) (\\w+)"
 let re_keyvalue = Pcre.regexp "^(\\w+): (.*)"
@@ -92,8 +97,8 @@ let list_kernels path =
   (* Parse in the *.info files.  These have historically had a few different
    * formats that we need to support.
    *)
-  let infos = List.map (
-    fun filename ->
+  let infos = List.mapi (
+    fun filename ->
       (* Get the basename (for getting the .data file later on). *)
       let basename = Filename.chop_suffix filename ".info" in
 
@@ -146,9 +151,27 @@ let list_kernels path =
 
       (*printf "%s -> %s %s\n%!" basename version arch;*)
 
-      { basename = basename; arch = arch;
+      { kv_i = i;
+       basename = basename; arch = arch;
        kernel_version = version }
   ) infos in
+
+  (* Check the .data, .data.gz or .data.bz2 file exists, and skip with
+   * a warning if not.
+   *)
+  let infos = List.filter (
+    fun { basename = basename } ->
+      if not (file_exists (basename ^ ".data")) &&
+       not (file_exists (basename ^ ".data.gz")) &&
+       not (file_exists (basename ^ ".data.bz2")) then (
+         eprintf "warning: %s: no data file found for this kernel - skipping\n%!"
+           basename;
+         false
+       )
+      else
+       true
+  ) infos in
+
   infos
 
 (* XXX This would be better as a proper lex/yacc parser.
@@ -173,10 +196,6 @@ let load_structures { basename = basename } struct_names =
   ) struct_names;
 
   (* Now read the data file and parse out the structures of interest. *)
-  let file_exists name =
-    try Unix.access name [Unix.F_OK]; true
-    with Unix.Unix_error _ -> false
-  in
   let close_process_in cmd chan =
     match Unix.close_process_in chan with
     | Unix.WEXITED 0 -> ()
@@ -435,11 +454,27 @@ let get_fields structures =
    *)
   let h = Hashtbl.create 13 in
 
+  (* A hash to check for fields which aren't always available by
+   * counting the number of times we see each field.
+   *)
+  let count, get =
+    let h = Hashtbl.create 13 in
+    let count field_name =
+      let r =
+       try Hashtbl.find h field_name
+       with Not_found -> let r = ref 0 in Hashtbl.add h field_name r; r in
+      incr r
+    in
+    let get field_name = try !(Hashtbl.find h field_name) with Not_found -> 0 in
+    count, get
+  in
+
   List.iter (
     fun ({kernel_version = version},
         {struct_name = struct_name; struct_fields = fields}) ->
       List.iter (
        fun {field_name = name; field_type = typ} ->
+         count name;
          try
            let (field_type, version_first_seen) = Hashtbl.find h name in
            if typ <> field_type then (
@@ -458,10 +493,13 @@ let get_fields structures =
       ) fields
   ) structures;
 
+  let nr_kernels = List.length structures in
+
   let fields =
     Hashtbl.fold (
       fun name (typ, _) fields ->
-       (name, typ) :: fields
+       let always_available = get name = nr_kernels in
+       (name, (typ, always_available)) :: fields
     ) h [] in
 
   List.sort fields