-(*
- List.iter (
- fun (basename, version, structures) ->
- printf "%s (version: %s):\n" basename version;
- List.iter (
- fun (struct_name, fields) ->
- printf " struct %s {\n" struct_name;
- List.iter (
- fun (field_name, (typ, offset, size)) ->
- (match typ with
- | `Int -> printf " int %s; " field_name
- | `Ptr struct_name ->
- printf " struct %s *%s; " struct_name field_name
- | `Str width ->
- printf " char %s[%d]; " field_name width
- );
- printf " /* offset = %d, size = %d */\n" offset size
- ) fields;
- printf " }\n\n";
- ) structures;
- ) datas;
-*)
+ let files =
+ List.map (
+ fun (name, _) ->
+ name,
+ List.filter_map (
+ fun (basename, version, arch, structures) ->
+ try Some (basename, version, arch, List.assoc name structures)
+ with Not_found -> None
+ ) datas
+ ) what in
+
+ let datas = () in ignore datas; (* garbage collect *)
+
+ (* Get just the field types. It's plausible that a field with the
+ * same name has a different type between kernel versions, so we must
+ * check that didn't happen.
+ *)
+ let files = List.map (
+ fun (struct_name, kernels) ->
+ let field_types =
+ match kernels with
+ | [] -> []
+ | (_, _, _, fields) :: kernels ->
+ let field_types_of_fields fields =
+ List.sort (
+ List.map (
+ fun (field_name, (typ, _, _)) -> field_name, typ
+ ) fields
+ )
+ in
+ let field_types = field_types_of_fields fields in
+ List.iter (
+ fun (_, _, _, fields) ->
+ if field_types <> field_types_of_fields fields then
+ failwith (sprintf "%s: one of the structure fields changed type between kernel versions" struct_name)
+ ) kernels;
+ field_types in
+ (struct_name, kernels, field_types)
+ ) files in
+
+ (* To minimize generated code size, we want to fold together all
+ * structures where the particulars (eg. offsets, sizes, endianness)
+ * of the fields we care about are the same -- eg. between kernel
+ * versions which are very similar.
+ *)
+ let endian_of_architecture arch =
+ if String.starts_with arch "i386" ||
+ String.starts_with arch "i486" ||
+ String.starts_with arch "i586" ||
+ String.starts_with arch "i686" ||
+ String.starts_with arch "x86_64" ||
+ String.starts_with arch "x86-64" then
+ Bitstring.LittleEndian
+ else if String.starts_with arch "ia64" then
+ Bitstring.LittleEndian (* XXX usually? *)
+ else if String.starts_with arch "ppc" then
+ Bitstring.BigEndian
+ else if String.starts_with arch "sparc" then
+ Bitstring.BigEndian
+ else
+ failwith (sprintf "endian_of_architecture: cannot parse %S" arch)
+ in