Version 1.7.6.
[libguestfs.git] / generator / generator_c.ml
index ca14d14..0194e0c 100644 (file)
@@ -24,6 +24,7 @@ open Generator_types
 open Generator_utils
 open Generator_pr
 open Generator_docstrings
+open Generator_api_versions
 open Generator_optgroups
 open Generator_actions
 open Generator_structs
@@ -84,9 +85,11 @@ let rec generate_prototype ?(extern = true) ?(static = false)
     let next () =
       if !comma then (
         if single_line then pr ", "
-        else
-          pr ",\n%s%s"
-            indent (spaces (String.length prefix + String.length name + 2))
+        else (
+          let namelen = String.length prefix + String.length name +
+                        String.length suffix + 2 in
+          pr ",\n%s%s" indent (spaces namelen)
+        )
       );
       comma := true
     in
@@ -113,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 (
@@ -223,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 _ ->
@@ -252,20 +257,22 @@ L</KEYS AND PASSPHRASES> for more information.\n\n";
          | None -> ()
          | Some txt -> pr "%s\n\n" txt
         );
+        (match lookup_api_version name with
+         | Some version -> pr "(Added in %s)\n\n" version
+         | None -> ()
+        );
 
         (* Handling of optional argument variants. *)
         if optargs <> [] then (
           pr "=head2 %s_va\n\n" name;
-          pr " ";
-          generate_prototype ~extern:false ~handle:"g"
+          generate_prototype ~extern:false ~indent:" " ~handle:"g"
             ~prefix:"guestfs_" ~suffix:"_va" ~optarg_proto:VA
             shortname style;
           pr "\n\n";
           pr "This is the \"va_list variant\" of L</%s>.\n\n" name;
           pr "See L</CALLS WITH OPTIONAL ARGUMENTS>.\n\n";
           pr "=head2 %s_argv\n\n" name;
-          pr " ";
-          generate_prototype ~extern:false ~handle:"g"
+          generate_prototype ~extern:false ~indent:" " ~handle:"g"
             ~prefix:"guestfs_" ~suffix:"_argv" ~optarg_proto:Argv
             shortname style;
           pr "\n\n";
@@ -329,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. *)
@@ -375,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 =
@@ -427,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 () =
@@ -531,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;
@@ -607,10 +733,12 @@ check_state (guestfs_h *g, const char *caller)
       | Pathname n
       | Dev_or_Path n
       | FileIn n
-      | FileOut n
-      | Key n ->
+      | FileOut n ->
           (* guestfish doesn't support string escaping, so neither do we *)
           pr "    fprintf (stderr, \" \\\"%%s\\\"\", %s);\n" n
+      | Key n ->
+          (* don't print keys *)
+          pr "    fprintf (stderr, \" \\\"***\\\"\");\n"
       | OptString n ->                 (* string option *)
           pr "    if (%s) fprintf (stderr, \" \\\"%%s\\\"\", %s);\n" n n;
           pr "    else fprintf (stderr, \" null\");\n"
@@ -632,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. *)
@@ -763,6 +893,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);