+
+(** {2 Transpose and check field types}
+
+ After we've used {!load_structures} for each kernel, we end
+ up with a list of kernels, and within that a list of structures
+ supported by the kernel. What we really want is to see how
+ each structure changes over time, and also to check if field
+ types have changed between versions (which we currently disallow).
+
+ The {!transpose} operation transposes the original list
+ of kernels to a list of structures.
+
+ The {!get_fields} operation gets a complete list of fields
+ and their types, and checks that the types haven't changed over
+ kernel versions. (Note that particular fields can be missing from
+ some kernel version, but that is OK).
+*)
+
+val transpose : string list ->
+ (info * (string * structure) list) list ->
+ (string * (info * structure) list) list
+ (** Transpose list of kernels to list of structures. The result
+ shows, for each structure, how it changed over kernel versions.
+
+ The first parameter is the list of structure names of interest,
+ and should be the same as was passed to {!load_structures}. *)
+
+val get_fields : (info * structure) list -> (string * (f_type * bool)) list
+ (** This gets a complete list of fields which have appeared in
+ any kernel version.
+
+ The return list contains [(field_name, (field_type,
+ always_present))] where [always_present] is a boolean flag which
+ is true if the field is present in every kernel version we
+ examined.
+
+ Fields must not change type between kernel versions - if
+ so this function prints an error and exits. (We may support
+ fields which change type in future, but we don't right now).
+ "Type" is quite widely defined here, see {!f_type}, and so
+ certain changes such as between sizes of ints are allowed,
+ but you can't have a field which once was a pointer and then
+ became a string or anything like that.
+
+ Note that a field may not be present in particular kernel
+ versions, but if it appears at all in any version, then it
+ will be in the result list. *)