[Libguestfs] [PATCH 1/3] src: generate code for printing contents of structs

Pino Toscano ptoscano at redhat.com
Wed Feb 24 12:52:02 UTC 2016


Extend the generator to generate a source (and the header for it) with
functions that print the content of a guestfs struct.  The code is
modelled after the code for it in fish.ml, although made a bit more
generic (destination FILE*, line separator) so it can be used also in
the library, when tracing.

This just introduces the new code and builds it as part of the helper
libutils.la.
---
 .gitignore        |   2 +
 generator/c.ml    | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 generator/c.mli   |   2 +
 generator/main.ml |   2 +
 po/POTFILES       |   1 +
 src/Makefile.am   |   6 ++-
 6 files changed, 136 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index 40bebb3..1493011 100644
--- a/.gitignore
+++ b/.gitignore
@@ -468,6 +468,8 @@ Makefile.in
 /src/structs-compare.c
 /src/structs-copy.c
 /src/structs-free.c
+/src/structs-print.c
+/src/structs-print.h
 /src/test-utils
 /stamp-h1
 /sysprep/.depend
diff --git a/generator/c.ml b/generator/c.ml
index 417e2bc..9af4529 100644
--- a/generator/c.ml
+++ b/generator/c.ml
@@ -1204,6 +1204,130 @@ and generate_client_structs_cleanup () =
 
   ) structs
 
+(* Generate structs-print.c file. *)
+and generate_client_structs_print_c () =
+  generate_header CStyle LGPLv2plus;
+
+  pr "\
+#include <config.h>
+
+#include <inttypes.h>
+
+#include \"c-ctype.h\"
+
+#include \"guestfs.h\"
+#include \"structs-print.h\"
+
+";
+
+  let write_structs =
+    List.iter (
+      fun { s_name = typ; s_cols = cols } ->
+        let needs_i =
+          List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
+
+        pr "void\n";
+        pr "guestfs_int_print_%s_indent (struct guestfs_%s *%s, FILE *dest, const char *linesep, const char *indent)\n"
+          typ typ typ;
+        pr "{\n";
+        if needs_i then (
+          pr "  size_t i;\n";
+          pr "\n"
+        );
+        List.iter (
+          function
+          | name, FString ->
+              pr "  fprintf (dest, \"%%s%s: %%s%%s\", indent, %s->%s, linesep);\n"
+                name typ name
+          | name, FUUID ->
+              pr "  fprintf (dest, \"%%s%s: \", indent);\n" name;
+              pr "  for (i = 0; i < 32; ++i)\n";
+              pr "    fprintf (dest, \"%%c\", %s->%s[i]);\n" typ name;
+              pr "  fprintf (dest, \"%%s\", linesep);\n"
+          | name, FBuffer ->
+              pr "  fprintf (dest, \"%%s%s: \", indent);\n" name;
+              pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
+              pr "    if (c_isprint (%s->%s[i]))\n" typ name;
+              pr "      fprintf (dest, \"%%c\", %s->%s[i]);\n" typ name;
+              pr "    else\n";
+              pr "      fprintf (dest, \"\\\\x%%02x\", (unsigned) %s->%s[i]);\n"
+                 typ name;
+              pr "  fprintf (dest, \"%%s\", linesep);\n"
+          | name, (FUInt64|FBytes) ->
+              pr "  fprintf (dest, \"%%s%s: %%\" PRIu64 \"%%s\", indent, %s->%s, linesep);\n"
+                name typ name
+          | name, FInt64 ->
+              pr "  fprintf (dest, \"%%s%s: %%\" PRIi64 \"%%s\", indent, %s->%s, linesep);\n"
+                name typ name
+          | name, FUInt32 ->
+              pr "  fprintf (dest, \"%%s%s: %%\" PRIu32 \"%%s\", indent, %s->%s, linesep);\n"
+                name typ name
+          | name, FInt32 ->
+              pr "  fprintf (dest, \"%%s%s: %%\" PRIi32 \"%%s\", indent, %s->%s, linesep);\n"
+                name typ name
+          | name, FChar ->
+              pr "  fprintf (dest, \"%%s%s: %%c%%s\", indent, %s->%s, linesep);\n"
+                name typ name
+          | name, FOptPercent ->
+              pr "  if (%s->%s >= 0)\n" typ name;
+              pr "    fprintf (dest, \"%%s%s: %%g %%%%%%s\", indent, (double) %s->%s, linesep);\n"
+                name typ name;
+              pr "  else\n";
+              pr "    fprintf (dest, \"%%s%s: %%s\", indent, linesep);\n" name
+        ) cols;
+        pr "}\n";
+        pr "\n";
+    ) in
+
+  write_structs external_structs;
+
+  pr "\
+#if GUESTFS_PRIVATE
+
+";
+
+  write_structs internal_structs;
+
+  pr "\
+#endif /* End of GUESTFS_PRIVATE. */
+"
+
+(* Generate structs-print.h file. *)
+and generate_client_structs_print_h () =
+  generate_header CStyle LGPLv2plus;
+
+  pr "\
+#ifndef GUESTFS_INTERNAL_STRUCTS_PRINT_H_
+#define GUESTFS_INTERNAL_STRUCTS_PRINT_H_
+
+#include <stdio.h>
+
+";
+
+  let write_structs =
+    List.iter (
+      fun { s_name = name } ->
+        pr "extern void guestfs_int_print_%s_indent (struct guestfs_%s *%s, FILE *dest, const char *linesep, const char *indent);\n"
+          name name name
+    ) in
+
+  write_structs external_structs;
+
+  pr "\
+
+#if GUESTFS_PRIVATE
+
+";
+
+  write_structs internal_structs;
+
+  pr "\
+
+#endif /* End of GUESTFS_PRIVATE. */
+
+#endif /* GUESTFS_INTERNAL_STRUCTS_PRINT_H_ */
+"
+
 (* Generate the client-side dispatch stubs. *)
 and generate_client_actions hash () =
   generate_header CStyle LGPLv2plus;
diff --git a/generator/c.mli b/generator/c.mli
index 9a261a4..156b244 100644
--- a/generator/c.mli
+++ b/generator/c.mli
@@ -32,6 +32,8 @@ val generate_client_structs_cleanup : unit -> unit
 val generate_client_structs_compare : unit -> unit
 val generate_client_structs_copy : unit -> unit
 val generate_client_structs_free : unit -> unit
+val generate_client_structs_print_h : unit -> unit
+val generate_client_structs_print_c : unit -> unit
 val generate_event_string_c : unit -> unit
 val generate_guestfs_h : unit -> unit
 val generate_internal_actions_h : unit -> unit
diff --git a/generator/main.ml b/generator/main.ml
index 63a5d25..8d08d83 100644
--- a/generator/main.ml
+++ b/generator/main.ml
@@ -99,6 +99,8 @@ Run it from the top source directory using the command
   output_to "src/structs-copy.c" generate_client_structs_copy;
   output_to "src/structs-free.c" generate_client_structs_free;
   output_to "src/structs-cleanup.c" generate_client_structs_cleanup;
+  output_to "src/structs-print.c" generate_client_structs_print_c;
+  output_to "src/structs-print.h" generate_client_structs_print_h;
   output_to "src/actions-variants.c" generate_client_actions_variants;
 
   for i = 0 to nr_actions_files-1 do
diff --git a/po/POTFILES b/po/POTFILES
index 2a1e313..0fb99b0 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -353,6 +353,7 @@ src/structs-cleanup.c
 src/structs-compare.c
 src/structs-copy.c
 src/structs-free.c
+src/structs-print.c
 src/test-utils.c
 src/tmpdirs.c
 src/utils.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 3ebb7f5..60641bf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -46,7 +46,9 @@ generator_built = \
 	structs-cleanup.c \
 	structs-compare.c \
 	structs-copy.c \
-	structs-free.c
+	structs-free.c \
+	structs-print.c \
+	structs-print.h
 
 BUILT_SOURCES = \
 	$(generator_built) \
@@ -226,6 +228,8 @@ endif
 libutils_la_SOURCES = \
 	cleanup.c \
 	structs-cleanup.c \
+	structs-print.c \
+	structs-print.h \
 	utils.c
 libutils_la_CPPFLAGS = $(libguestfs_la_CPPFLAGS)
 libutils_la_CFLAGS = $(libguestfs_la_CFLAGS)
-- 
2.5.0




More information about the Libguestfs mailing list