[Libguestfs] [PATCH v2 4/7] generator: Use an OCaml struct to store the structs.

Richard W.M. Jones rjones at redhat.com
Tue Oct 30 11:57:12 UTC 2012


From: "Richard W.M. Jones" <rjones at redhat.com>

This just makes it simpler to add extra fields to each struct.

This is code motion, although the output of the generator changes very
slightly: the camel-cased structs are no longer stored sorted, so the
generated lists in java/Makefile.in and
java/com/redhat/et/libguestfs/.gitignore change order.
---
 generator/c.ml                           |   8 +-
 generator/csharp.ml                      |   2 +-
 generator/erlang.ml                      |   2 +-
 generator/fish.ml                        |   2 +-
 generator/gobject.ml                     |   2 +-
 generator/java.ml                        |   6 +-
 generator/main.ml                        |   6 +-
 generator/ocaml.ml                       |   4 +-
 generator/python.ml                      |   2 +-
 generator/structs.ml                     | 165 ++++++++++++++++++-------------
 generator/structs.mli                    |  18 ++--
 generator/xdr.ml                         |   3 +-
 java/Makefile.inc                        |  24 ++---
 java/com/redhat/et/libguestfs/.gitignore |  24 ++---
 14 files changed, 153 insertions(+), 115 deletions(-)

diff --git a/generator/c.ml b/generator/c.ml
index 798a3a3..54f35b5 100644
--- a/generator/c.ml
+++ b/generator/c.ml
@@ -311,7 +311,7 @@ and generate_actions_pod_back_compat_entry { name = name;
 and generate_structs_pod () =
   (* Structs documentation. *)
   List.iter (
-    fun (typ, cols) ->
+    fun { s_name = typ; s_cols = cols } ->
       pr "=head2 guestfs_%s\n" typ;
       pr "\n";
       pr " struct guestfs_%s {\n" typ;
@@ -542,7 +542,7 @@ extern GUESTFS_DLL_PUBLIC void *guestfs_next_private (guestfs_h *g, const char *
 
   (* Public structures. *)
   List.iter (
-    fun (typ, cols) ->
+    fun { s_name = typ; s_cols = cols } ->
       pr "struct guestfs_%s {\n" typ;
       List.iter (
         function
@@ -710,7 +710,7 @@ and generate_client_free_structs () =
   pr "\n";
 
   List.iter (
-    fun (typ, _) ->
+    fun { s_name = typ } ->
       pr "GUESTFS_DLL_PUBLIC void\n";
       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
       pr "{\n";
@@ -1661,7 +1661,7 @@ and generate_linker_script () =
     ) in
   let structs =
     List.concat (
-      List.map (fun (typ, _) ->
+      List.map (fun { s_name = typ } ->
                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
         structs
     ) in
diff --git a/generator/csharp.ml b/generator/csharp.ml
index 9f86f48..803a4a5 100644
--- a/generator/csharp.ml
+++ b/generator/csharp.ml
@@ -110,7 +110,7 @@ namespace Guestfs
    * method names (eg. "class stat" and "stat").
    *)
   List.iter (
-    fun (typ, cols) ->
+    fun { s_name = typ; s_cols = cols } ->
       pr "    [StructLayout (LayoutKind.Sequential)]\n";
       pr "    public class _%s {\n" typ;
       List.iter (
diff --git a/generator/erlang.ml b/generator/erlang.ml
index 673394e..6c7eb70 100644
--- a/generator/erlang.ml
+++ b/generator/erlang.ml
@@ -237,7 +237,7 @@ extern void free_strings (char **r);
   in
 
   List.iter (
-    fun (typ, cols) ->
+    fun { s_name = typ; s_cols = cols } ->
       pr "static ETERM *\n";
       pr "make_%s (const struct guestfs_%s *%s)\n" typ typ typ;
       pr "{\n";
diff --git a/generator/fish.ml b/generator/fish.ml
index 76377a2..59c1114 100644
--- a/generator/fish.ml
+++ b/generator/fish.ml
@@ -227,7 +227,7 @@ Guestfish will prompt for these separately."
 
   (* print_* functions *)
   List.iter (
-    fun (typ, cols) ->
+    fun { s_name = typ; s_cols = cols } ->
       let needs_i =
         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
 
diff --git a/generator/gobject.ml b/generator/gobject.ml
index 2cd1809..6c35e02 100644
--- a/generator/gobject.ml
+++ b/generator/gobject.ml
@@ -107,7 +107,7 @@ let filenames =
   "session" :: "tristate" ::
 
   (* structs *)
-  List.map (function typ, cols -> "struct-" ^ typ) structs @
+  List.map (fun { s_name = typ } -> "struct-" ^ typ) structs @
 
   (* optargs *)
   List.map (function { name = name } -> "optargs-" ^ name) (
diff --git a/generator/java.ml b/generator/java.ml
index 1e06c62..bffe077 100644
--- a/generator/java.ml
+++ b/generator/java.ml
@@ -875,10 +875,10 @@ and generate_java_makefile_inc () =
 
   pr "java_built_sources = \\\n";
   List.iter (
-    fun (typ, jtyp) ->
+    fun { s_name = typ; s_camel_name = jtyp } ->
         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
-  ) camel_structs;
+  ) structs;
   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
 
 and generate_java_gitignore () =
-  List.iter (fun (_, jtyp) -> pr "%s.java\n" jtyp) camel_structs
+  List.iter (fun { s_camel_name = jtyp } -> pr "%s.java\n" jtyp) structs
diff --git a/generator/main.ml b/generator/main.ml
index 8d60850..98f4b31 100644
--- a/generator/main.ml
+++ b/generator/main.ml
@@ -124,11 +124,11 @@ Run it from the top source directory using the command
   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
 
   List.iter (
-    fun (typ, jtyp) ->
+    fun { s_name = typ; s_camel_name = jtyp } ->
       let cols = cols_of_struct typ in
       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
       output_to filename (generate_java_struct jtyp cols)
-  ) camel_structs;
+  ) structs;
   delete_except_generated
     ~skip:["java/com/redhat/et/libguestfs/LibGuestFSException.java"]
     "java/com/redhat/et/libguestfs/*.java";
@@ -152,7 +152,7 @@ Run it from the top source directory using the command
   output_to "gobject/docs/guestfs-title.sgml" generate_gobject_doc_title;
 
   List.iter (
-    fun (typ, cols) ->
+    fun { s_name = typ; s_cols = cols } ->
       let short = sprintf "struct-%s" typ in
       let filename =
         sprintf "gobject/include/guestfs-gobject/%s.h" short in
diff --git a/generator/ocaml.ml b/generator/ocaml.ml
index b90aeb8..f9ac5ca 100644
--- a/generator/ocaml.ml
+++ b/generator/ocaml.ml
@@ -377,7 +377,7 @@ copy_table (char * const * argv)
   in
 
   List.iter (
-    fun (typ, cols) ->
+    fun { s_name = typ; s_cols = cols } ->
       let has_optpercent_col =
         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
 
@@ -672,7 +672,7 @@ copy_table (char * const * argv)
 
 and generate_ocaml_structure_decls () =
   List.iter (
-    fun (typ, cols) ->
+    fun { s_name = typ; s_cols = cols } ->
       pr "type %s = {\n" typ;
       List.iter (
         function
diff --git a/generator/python.ml b/generator/python.ml
index 3975055..0e754db 100644
--- a/generator/python.ml
+++ b/generator/python.ml
@@ -160,7 +160,7 @@ free_strings (char **argv)
 
   (* Structures, turned into Python dictionaries. *)
   List.iter (
-    fun (typ, cols) ->
+    fun { s_name = typ; s_cols = cols } ->
       pr "static PyObject *\n";
       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
       pr "{\n";
diff --git a/generator/structs.ml b/generator/structs.ml
index d62fcc5..4c8e2ef 100644
--- a/generator/structs.ml
+++ b/generator/structs.ml
@@ -22,6 +22,11 @@ open Types
 open Utils
 
 type cols = (string * field) list
+type struc = {
+  s_name : string;
+  s_cols : cols;
+  s_camel_name : string;
+}
 
 (* Because we generate extra parsing code for LVM command line tools,
  * we have to pull out the LVM columns separately here.
@@ -88,6 +93,8 @@ let lvm_lv_cols = [
   "modules", FString;
 ]
 
+let defaults = { s_name = ""; s_cols = []; s_camel_name = "" }
+
 (* Names and fields in all structures (in RStruct and RStructList)
  * that we support.
  *)
@@ -95,21 +102,29 @@ let structs = [
   (* The old RIntBool return type, only ever used for aug_defnode.  Do
    * not use this struct in any new code.
    *)
-  "int_bool", [
+  { defaults with
+    s_name = "int_bool";
+    s_cols = [
     "i", FInt32;		(* for historical compatibility *)
     "b", FInt32;		(* for historical compatibility *)
-  ];
+    ];
+    s_camel_name = "IntBool" };
 
   (* LVM PVs, VGs, LVs. *)
-  "lvm_pv", lvm_pv_cols;
-  "lvm_vg", lvm_vg_cols;
-  "lvm_lv", lvm_lv_cols;
+  { defaults with
+    s_name = "lvm_pv"; s_cols = lvm_pv_cols; s_camel_name = "PV" };
+  { defaults with
+    s_name = "lvm_vg"; s_cols = lvm_vg_cols; s_camel_name = "VG" };
+  { defaults with
+    s_name = "lvm_lv"; s_cols = lvm_lv_cols; s_camel_name = "LV" };
 
   (* Column names and types from stat structures.
    * NB. Can't use things like 'st_atime' because glibc header files
    * define some of these as macros.  Ugh.
    *)
-  "stat", [
+  { defaults with
+    s_name = "stat";
+    s_cols = [
     "dev", FInt64;
     "ino", FInt64;
     "mode", FInt64;
@@ -123,8 +138,11 @@ let structs = [
     "atime", FInt64;
     "mtime", FInt64;
     "ctime", FInt64;
-  ];
-  "statvfs", [
+    ];
+    s_camel_name = "Stat" };
+  { defaults with
+    s_name = "statvfs";
+    s_cols = [
     "bsize", FInt64;
     "frsize", FInt64;
     "blocks", FInt64;
@@ -136,48 +154,66 @@ let structs = [
     "fsid", FInt64;
     "flag", FInt64;
     "namemax", FInt64;
-  ];
+    ];
+    s_camel_name = "StatVFS" };
 
   (* Column names in dirent structure. *)
-  "dirent", [
+  { defaults with
+    s_name = "dirent";
+    s_cols = [
     "ino", FInt64;
     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
     "ftyp", FChar;
     "name", FString;
-  ];
+    ];
+    s_camel_name = "Dirent" };
 
   (* Version numbers. *)
-  "version", [
+  { defaults with
+    s_name = "version";
+    s_cols = [
     "major", FInt64;
     "minor", FInt64;
     "release", FInt64;
     "extra", FString;
-  ];
+    ];
+    s_camel_name = "Version" };
 
   (* Extended attribute. *)
-  "xattr", [
+  { defaults with
+    s_name = "xattr";
+    s_cols = [
     "attrname", FString;
     "attrval", FBuffer;
-  ];
+    ];
+    s_camel_name = "XAttr" };
 
   (* Inotify events. *)
-  "inotify_event", [
+  { defaults with
+    s_name = "inotify_event";
+    s_cols = [
     "in_wd", FInt64;
     "in_mask", FUInt32;
     "in_cookie", FUInt32;
     "in_name", FString;
-  ];
+    ];
+    s_camel_name = "INotifyEvent" };
 
   (* Partition table entry. *)
-  "partition", [
+  { defaults with
+    s_name = "partition";
+    s_cols = [
     "part_num", FInt32;
     "part_start", FBytes;
     "part_end", FBytes;
     "part_size", FBytes;
-  ];
+    ];
+    s_camel_name = "Partition" };
 
   (* Application. *)
-  "application", [
+  { defaults with
+    s_name = "application";
+    s_cols = [
     "app_name", FString;
     "app_display_name", FString;
     "app_epoch", FInt32;
@@ -190,10 +226,13 @@ let structs = [
     "app_source_package", FString;
     "app_summary", FString;
     "app_description", FString;
-  ];
+    ];
+    s_camel_name = "Application" };
 
   (* ISO primary volume descriptor. *)
-  "isoinfo", [
+  { defaults with
+    s_name = "isoinfo";
+    s_cols = [
     "iso_system_id", FString;
     "iso_volume_id", FString;
     "iso_volume_space_size", FUInt32;
@@ -211,24 +250,33 @@ let structs = [
     "iso_volume_modification_t", FInt64;
     "iso_volume_expiration_t", FInt64;
     "iso_volume_effective_t", FInt64;
-  ];
+    ];
+    s_camel_name = "ISOInfo" };
 
   (* /proc/mdstat information.  See linux.git/drivers/md/md.c *)
-  "mdstat", [
+  { defaults with
+    s_name = "mdstat";
+    s_cols = [
     "mdstat_device", FString;
     "mdstat_index", FInt32;
     "mdstat_flags", FString;
-  ];
+    ];
+    s_camel_name = "MDStat" };
 
   (* btrfs subvolume list output *)
-  "btrfssubvolume", [
+  { defaults with
+    s_name = "btrfssubvolume";
+    s_cols = [
     "btrfssubvolume_id", FUInt64;
     "btrfssubvolume_top_level_id", FUInt64;
     "btrfssubvolume_path", FString;
-  ];
+    ];
+    s_camel_name = "BTRFSSubvolume" };
 
   (* XFS info descriptor. *)
-  "xfsinfo", [
+  { defaults with
+    s_name = "xfsinfo";
+    s_cols = [
     "xfs_mntpoint", FString;
     "xfs_inodesize", FUInt32;
     "xfs_agcount", FUInt32;
@@ -254,60 +302,45 @@ let structs = [
     "xfs_rtextsize", FUInt32;
     "xfs_rtblocks", FUInt64;
     "xfs_rtextents", FUInt64;
-  ];
+    ];
+    s_camel_name = "XFSInfo" };
 
   (* utsname *)
-  "utsname", [
+  { defaults with
+    s_name = "utsname";
+    s_cols = [
     "uts_sysname", FString;
     "uts_release", FString;
     "uts_version", FString;
     "uts_machine", FString;
-  ];
+    ];
+    s_camel_name = "UTSName" };
 
   (* Used by hivex_* APIs to return a list of int64 handles (node
    * handles and value handles).  Note that we can't add a putative
    * 'RInt64List' type to the generator because we need to return
    * length and size, and RStructList does this already.
    *)
-  "hivex_node", [
+  { defaults with
+    s_name = "hivex_node";
+    s_cols = [
     "hivex_node_h", FInt64;
-  ];
-  "hivex_value", [
+    ];
+    s_camel_name = "HivexNode" };
+  { defaults with
+    s_name = "hivex_value";
+    s_cols = [
     "hivex_value_h", FInt64;
-  ];
+    ];
+    s_camel_name = "HivexValue" };
 ] (* end of structs *)
 
-(* For bindings which want camel case *)
-let camel_structs = [
-  "int_bool", "IntBool";
-  "lvm_pv", "PV";
-  "lvm_vg", "VG";
-  "lvm_lv", "LV";
-  "stat", "Stat";
-  "statvfs", "StatVFS";
-  "dirent", "Dirent";
-  "version", "Version";
-  "xattr", "XAttr";
-  "inotify_event", "INotifyEvent";
-  "partition", "Partition";
-  "application", "Application";
-  "isoinfo", "ISOInfo";
-  "xfsinfo", "XFSInfo";
-  "mdstat", "MDStat";
-  "btrfssubvolume", "BTRFSSubvolume";
-  "utsname", "UTSName";
-  "hivex_node", "HivexNode";
-  "hivex_value", "HivexValue";
-]
-let camel_structs = List.sort (fun (_,a) (_,b) -> compare a b) camel_structs
-
-let camel_name_of_struct typ =
-  try List.assoc typ camel_structs
+let lookup_struct name =
+  try List.find (fun { s_name = n } -> n = name) structs
   with Not_found ->
     failwithf
-      "camel_name_of_struct: no camel_structs entry corresponding to %s" typ
+      "lookup_struct: no structs entry corresponding to %s" name
 
-let cols_of_struct typ =
-  try List.assoc typ structs
-  with Not_found ->
-    failwithf "cols_of_struct: unknown struct %s" typ
+let camel_name_of_struct name = (lookup_struct name).s_camel_name
+
+let cols_of_struct name = (lookup_struct name).s_cols
diff --git a/generator/structs.mli b/generator/structs.mli
index 56987e0..05df115 100644
--- a/generator/structs.mli
+++ b/generator/structs.mli
@@ -23,11 +23,14 @@
 type cols = (string * Types.field) list
 (** List of structure fields (called "columns"). *)
 
-val structs : (string * cols) list
-(** List of structures. *)
+type struc = {
+  s_name : string;                      (** Regular name. *)
+  s_cols : cols;                        (** Columns. *)
+  s_camel_name : string;                (** Camel-cased name. *)
+}
 
-val camel_structs : (string * string) list
-(** For bindings which want camel case struct names *)
+val structs : struc list
+(** List of structures. *)
 
 val lvm_pv_cols : cols
 val lvm_vg_cols : cols
@@ -36,8 +39,11 @@ val lvm_lv_cols : cols
     used to generate code for parsing the output of commands like
     [lvs].  One day replace this with liblvm API calls. *)
 
+val lookup_struct : string -> struc
+(** Lookup a struct by name. *)
+
 val camel_name_of_struct : string -> string
-(** Camel case name of struct. *)
+(** Lookup struct by name, return the s_camel_name field. *)
 
 val cols_of_struct : string -> cols
-(** Extract columns of a struct. *)
+(** Lookup struct by name, return the s_cols field. *)
diff --git a/generator/xdr.ml b/generator/xdr.ml
index b45f2c4..46b1c90 100644
--- a/generator/xdr.ml
+++ b/generator/xdr.ml
@@ -70,8 +70,7 @@ let generate_xdr () =
   pr "/* Internal structures. */\n";
   pr "\n";
   List.iter (
-    function
-    | typ, cols ->
+    fun { s_name = typ; s_cols = cols } ->
         pr "struct guestfs_int_%s {\n" typ;
         List.iter (function
                    | name, FChar -> pr "  char %s;\n" name
diff --git a/java/Makefile.inc b/java/Makefile.inc
index 64b533a..aa9f96c 100644
--- a/java/Makefile.inc
+++ b/java/Makefile.inc
@@ -20,23 +20,23 @@
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
 java_built_sources = \
-	com/redhat/et/libguestfs/Application.java \
-	com/redhat/et/libguestfs/BTRFSSubvolume.java \
-	com/redhat/et/libguestfs/Dirent.java \
-	com/redhat/et/libguestfs/HivexNode.java \
-	com/redhat/et/libguestfs/HivexValue.java \
-	com/redhat/et/libguestfs/INotifyEvent.java \
-	com/redhat/et/libguestfs/ISOInfo.java \
 	com/redhat/et/libguestfs/IntBool.java \
-	com/redhat/et/libguestfs/LV.java \
-	com/redhat/et/libguestfs/MDStat.java \
 	com/redhat/et/libguestfs/PV.java \
-	com/redhat/et/libguestfs/Partition.java \
+	com/redhat/et/libguestfs/VG.java \
+	com/redhat/et/libguestfs/LV.java \
 	com/redhat/et/libguestfs/Stat.java \
 	com/redhat/et/libguestfs/StatVFS.java \
-	com/redhat/et/libguestfs/UTSName.java \
-	com/redhat/et/libguestfs/VG.java \
+	com/redhat/et/libguestfs/Dirent.java \
 	com/redhat/et/libguestfs/Version.java \
 	com/redhat/et/libguestfs/XAttr.java \
+	com/redhat/et/libguestfs/INotifyEvent.java \
+	com/redhat/et/libguestfs/Partition.java \
+	com/redhat/et/libguestfs/Application.java \
+	com/redhat/et/libguestfs/ISOInfo.java \
+	com/redhat/et/libguestfs/MDStat.java \
+	com/redhat/et/libguestfs/BTRFSSubvolume.java \
 	com/redhat/et/libguestfs/XFSInfo.java \
+	com/redhat/et/libguestfs/UTSName.java \
+	com/redhat/et/libguestfs/HivexNode.java \
+	com/redhat/et/libguestfs/HivexValue.java \
 	com/redhat/et/libguestfs/GuestFS.java
diff --git a/java/com/redhat/et/libguestfs/.gitignore b/java/com/redhat/et/libguestfs/.gitignore
index 72a1144..eb332a8 100644
--- a/java/com/redhat/et/libguestfs/.gitignore
+++ b/java/com/redhat/et/libguestfs/.gitignore
@@ -1,19 +1,19 @@
-Application.java
-BTRFSSubvolume.java
-Dirent.java
-HivexNode.java
-HivexValue.java
-INotifyEvent.java
-ISOInfo.java
 IntBool.java
-LV.java
-MDStat.java
 PV.java
-Partition.java
+VG.java
+LV.java
 Stat.java
 StatVFS.java
-UTSName.java
-VG.java
+Dirent.java
 Version.java
 XAttr.java
+INotifyEvent.java
+Partition.java
+Application.java
+ISOInfo.java
+MDStat.java
+BTRFSSubvolume.java
 XFSInfo.java
+UTSName.java
+HivexNode.java
+HivexValue.java
-- 
1.7.11.4




More information about the Libguestfs mailing list