generator: Make trace flag an explicit variable.
[libguestfs.git] / generator / generator_c.ml
index 28cecdb..658d76d 100644 (file)
@@ -116,6 +116,9 @@ let rec generate_prototype ?(extern = true) ?(static = false)
           pr "const char *%s" n;
           next ();
           pr "size_t %s_size" n
+      | Pointer (t, n) ->
+          next ();
+          pr "%s %s" t n
     ) args;
     if is_RBufferOut then (next (); pr "size_t *size_r");
     if optargs <> [] then (
@@ -226,8 +229,7 @@ I<The caller must free the strings and the array after use>.\n\n"
 or NULL if there was an error.
 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
          | RStructList (_, typ) ->
-             pr "This function returns a C<struct guestfs_%s_list *>
-(see E<lt>guestfs-structs.hE<gt>),
+             pr "This function returns a C<struct guestfs_%s_list *>,
 or NULL if there was an error.
 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
          | RHashtable _ ->
@@ -255,8 +257,10 @@ L</KEYS AND PASSPHRASES> for more information.\n\n";
          | None -> ()
          | Some txt -> pr "%s\n\n" txt
         );
-        let version = lookup_api_version name in
-        pr "(Added in %s)\n\n" version;
+        (match lookup_api_version name with
+         | Some version -> pr "(Added in %s)\n\n" version
+         | None -> ()
+        );
 
         (* Handling of optional argument variants. *)
         if optargs <> [] then (
@@ -332,22 +336,119 @@ and generate_availability_pod () =
   pr "=back\n";
   pr "\n"
 
-(* Generate the guestfs-structs.h file. *)
-and generate_structs_h () =
+(* Generate the guestfs.h file. *)
+and generate_guestfs_h () =
   generate_header CStyle LGPLv2plus;
 
-  (* This is a public exported header file containing various
-   * structures.  The structures are carefully written to have
-   * exactly the same in-memory format as the XDR structures that
-   * we use on the wire to the daemon.  The reason for creating
-   * copies of these structures here is just so we don't have to
-   * export the whole of guestfs_protocol.h (which includes much
-   * unrelated and XDR-dependent stuff that we don't want to be
-   * public, or required by clients).
-   *
-   * To reiterate, we will pass these structures to and from the
-   * client with a simple assignment or memcpy, so the format
-   * must be identical to what rpcgen / the RFC defines.
+  pr "\
+/* ---------- IMPORTANT NOTE ----------
+ *
+ * All API documentation is in the manpage, 'guestfs(3)'.
+ * To read it, type:           man 3 guestfs
+ * Or read it online here:     http://libguestfs.org/guestfs.3.html
+ *
+ * Go and read it now, I'll be right here waiting for you
+ * when you come back.
+ *
+ * ------------------------------------
+ */
+
+#ifndef GUESTFS_H_
+#define GUESTFS_H_
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdarg.h>
+
+/* The handle. */
+#ifndef GUESTFS_TYPEDEF_H
+#define GUESTFS_TYPEDEF_H 1
+typedef struct guestfs_h guestfs_h;
+#endif
+
+/* Connection management. */
+extern guestfs_h *guestfs_create (void);
+extern void guestfs_close (guestfs_h *g);
+
+/* Error handling. */
+extern const char *guestfs_last_error (guestfs_h *g);
+#define LIBGUESTFS_HAVE_LAST_ERRNO 1
+extern int guestfs_last_errno (guestfs_h *g);
+
+#ifndef GUESTFS_TYPEDEF_ERROR_HANDLER_CB
+#define GUESTFS_TYPEDEF_ERROR_HANDLER_CB 1
+typedef void (*guestfs_error_handler_cb) (guestfs_h *g, void *opaque, const char *msg);
+#endif
+
+#ifndef GUESTFS_TYPEDEF_ABORT_CB
+#define GUESTFS_TYPEDEF_ABORT_CB 1
+typedef void (*guestfs_abort_cb) (void) __attribute__((__noreturn__));
+#endif
+
+extern void guestfs_set_error_handler (guestfs_h *g, guestfs_error_handler_cb cb, void *opaque);
+extern guestfs_error_handler_cb guestfs_get_error_handler (guestfs_h *g, void **opaque_rtn);
+
+extern void guestfs_set_out_of_memory_handler (guestfs_h *g, guestfs_abort_cb);
+extern guestfs_abort_cb guestfs_get_out_of_memory_handler (guestfs_h *g);
+
+/* Events. */
+#ifndef GUESTFS_TYPEDEF_LOG_MESSAGE_CB
+#define GUESTFS_TYPEDEF_LOG_MESSAGE_CB 1
+typedef void (*guestfs_log_message_cb) (guestfs_h *g, void *opaque, char *buf, int len);
+#endif
+
+#ifndef GUESTFS_TYPEDEF_SUBPROCESS_QUIT_CB
+#define GUESTFS_TYPEDEF_SUBPROCESS_QUIT_CB 1
+typedef void (*guestfs_subprocess_quit_cb) (guestfs_h *g, void *opaque);
+#endif
+
+#ifndef GUESTFS_TYPEDEF_LAUNCH_DONE_CB
+#define GUESTFS_TYPEDEF_LAUNCH_DONE_CB 1
+typedef void (*guestfs_launch_done_cb) (guestfs_h *g, void *opaque);
+#endif
+
+#ifndef GUESTFS_TYPEDEF_CLOSE_CB
+#define GUESTFS_TYPEDEF_CLOSE_CB 1
+typedef void (*guestfs_close_cb) (guestfs_h *g, void *opaque);
+#endif
+
+#ifndef GUESTFS_TYPEDEF_PROGRESS_CB
+#define GUESTFS_TYPEDEF_PROGRESS_CB 1
+typedef void (*guestfs_progress_cb) (guestfs_h *g, void *opaque, int proc_nr, int serial, uint64_t position, uint64_t total);
+#endif
+
+extern void guestfs_set_log_message_callback (guestfs_h *g, guestfs_log_message_cb cb, void *opaque);
+extern void guestfs_set_subprocess_quit_callback (guestfs_h *g, guestfs_subprocess_quit_cb cb, void *opaque);
+extern void guestfs_set_launch_done_callback (guestfs_h *g, guestfs_launch_done_cb cb, void *opaque);
+#define LIBGUESTFS_HAVE_SET_CLOSE_CALLBACK 1
+extern void guestfs_set_close_callback (guestfs_h *g, guestfs_close_cb cb, void *opaque);
+#define LIBGUESTFS_HAVE_SET_PROGRESS_CALLBACK 1
+extern void guestfs_set_progress_callback (guestfs_h *g, guestfs_progress_cb cb, void *opaque);
+
+/* Private data area. */
+#define LIBGUESTFS_HAVE_SET_PRIVATE 1
+extern void guestfs_set_private (guestfs_h *g, const char *key, void *data);
+#define LIBGUESTFS_HAVE_GET_PRIVATE 1
+extern void *guestfs_get_private (guestfs_h *g, const char *key);
+
+/* Structures. */
+";
+
+  (* The structures are carefully written to have exactly the same
+   * in-memory format as the XDR structures that we use on the wire to
+   * the daemon.  The reason for creating copies of these structures
+   * here is just so we don't have to export the whole of
+   * guestfs_protocol.h (which includes much unrelated and
+   * XDR-dependent stuff that we don't want to be public, or required
+   * by clients).
+   * 
+   * To reiterate, we will pass these structures to and from the client
+   * with a simple assignment or memcpy, so the format must be
+   * identical to what rpcgen / the RFC defines.
    *)
 
   (* Public structures. *)
@@ -378,11 +479,12 @@ and generate_structs_h () =
       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
       pr "\n"
-  ) structs
+  ) structs;
+
+  pr "\
+/* Actions. */
+";
 
-(* Generate the guestfs-actions.h file. *)
-and generate_actions_h () =
-  generate_header CStyle LGPLv2plus;
   List.iter (
     fun (shortname, (ret, args, optargs as style), _, flags, _, _, _) ->
       let deprecated =
@@ -430,7 +532,27 @@ and generate_actions_h () =
           ~prefix:"guestfs_" ~suffix:"_argv" ~optarg_proto:Argv
           shortname style;
       );
-  ) all_functions_sorted
+  ) all_functions_sorted;
+
+  pr "\
+
+/* Private functions.
+ *
+ * These are NOT part of the public, stable API, and can change at any
+ * time!  We export them because they are used by some of the language
+ * bindings.
+ */
+extern void *guestfs_safe_malloc (guestfs_h *g, size_t nbytes);
+extern void *guestfs_safe_calloc (guestfs_h *g, size_t n, size_t s);
+extern const char *guestfs_tmpdir (void);
+/* End of private functions. */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GUESTFS_H_ */
+"
 
 (* Generate the guestfs-internal-actions.h file. *)
 and generate_internal_actions_h () =
@@ -534,7 +656,8 @@ check_state (guestfs_h *g, const char *caller)
       | BufferIn n
       | StringList n
       | DeviceList n
-      | Key n ->
+      | Key n
+      | Pointer (_, n) ->
           pr "  if (%s == NULL) {\n" n;
           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
           pr "           \"%s\", \"%s\");\n" shortname n;
@@ -589,7 +712,7 @@ check_state (guestfs_h *g, const char *caller)
 
   (* Generate code to generate guestfish call traces. *)
   let trace_call shortname (ret, args, optargs) =
-    pr "  if (guestfs__get_trace (g)) {\n";
+    pr "  if (trace_flag) {\n";
 
     let needs_i =
       List.exists (function
@@ -637,6 +760,8 @@ check_state (guestfs_h *g, const char *caller)
       | BufferIn n ->                   (* RHBZ#646822 *)
           pr "    fputc (' ', stderr);\n";
           pr "    guestfs___print_BufferIn (stderr, %s, %s_size);\n" n n
+      | Pointer (t, n) ->
+          pr "    fprintf (stderr, \" (%s)%%p\", %s);\n" t n
     ) args;
 
     (* Optional arguments. *)
@@ -677,6 +802,8 @@ check_state (guestfs_h *g, const char *caller)
           ~handle:"g" ~prefix:"guestfs_" ~suffix:"_argv" ~optarg_proto:Argv
           shortname style;
       pr "{\n";
+      pr "  int trace_flag = g->trace;\n";
+      pr "\n";
       check_null_strings shortname style;
       reject_unknown_optargs shortname style;
       trace_call shortname style;
@@ -727,6 +854,7 @@ check_state (guestfs_h *g, const char *caller)
 
       pr "  int serial;\n";
       pr "  int r;\n";
+      pr "  int trace_flag = g->trace;\n";
       pr "\n";
       check_null_strings shortname style;
       reject_unknown_optargs shortname style;
@@ -768,6 +896,7 @@ check_state (guestfs_h *g, const char *caller)
                  pr "  }\n";
                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
                  pr "  args.%s.%s_len = %s_size;\n" n n n
+             | Pointer _ -> assert false
            ) args;
            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
              (String.uppercase shortname);