Enable deprecated option only with gcc >= 4.5.
[libguestfs.git] / generator / generator_c.ml
index aee2d77..8208306 100644 (file)
@@ -365,6 +365,20 @@ extern \"C\" {
 #include <stdint.h>
 #include <stdarg.h>
 
+#ifdef __GNUC__
+# define GUESTFS_GCC_VERSION \\
+    (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#endif
+
+/* Define GUESTFS_WARN_DEPRECATED=1 to warn about deprecated API functions. */
+#define GUESTFS_DEPRECATED_BY(s)
+#if GUESTFS_WARN_DEPRECATED
+#  if defined(__GNUC__) && GUESTFS_GCC_VERSION >= 40500 /* gcc >= 4.5 */
+#    undef GUESTFS_DEPRECATED_BY
+#    define GUESTFS_DEPRECATED_BY(s) __attribute__((__deprecated__(\"change the program to use guestfs_\" s \" instead of this deprecated function\")))
+#  endif
+#endif /* GUESTFS_WARN_DEPRECATED */
+
 /* The handle. */
 #ifndef GUESTFS_TYPEDEF_H
 #define GUESTFS_TYPEDEF_H 1
@@ -429,7 +443,7 @@ int guestfs_set_event_callback (guestfs_h *g,
 #define LIBGUESTFS_HAVE_DELETE_EVENT_CALLBACK 1
 void guestfs_delete_event_callback (guestfs_h *g, int event_handle);
 
-/* Old-style event handling.  In new code use guestfs_set_event_callback. */
+/* Old-style event handling. */
 #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);
@@ -455,13 +469,18 @@ typedef void (*guestfs_close_cb) (guestfs_h *g, void *opaque);
 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);
+extern void guestfs_set_log_message_callback (guestfs_h *g, guestfs_log_message_cb cb, void *opaque)
+  GUESTFS_DEPRECATED_BY(\"set_event_callback\");
+extern void guestfs_set_subprocess_quit_callback (guestfs_h *g, guestfs_subprocess_quit_cb cb, void *opaque)
+  GUESTFS_DEPRECATED_BY(\"set_event_callback\");
+extern void guestfs_set_launch_done_callback (guestfs_h *g, guestfs_launch_done_cb cb, void *opaque)
+  GUESTFS_DEPRECATED_BY(\"set_event_callback\");
 #define LIBGUESTFS_HAVE_SET_CLOSE_CALLBACK 1
-extern void guestfs_set_close_callback (guestfs_h *g, guestfs_close_cb cb, void *opaque);
+extern void guestfs_set_close_callback (guestfs_h *g, guestfs_close_cb cb, void *opaque)
+  GUESTFS_DEPRECATED_BY(\"set_event_callback\");
 #define LIBGUESTFS_HAVE_SET_PROGRESS_CALLBACK 1
-extern void guestfs_set_progress_callback (guestfs_h *g, guestfs_progress_cb cb, void *opaque);
+extern void guestfs_set_progress_callback (guestfs_h *g, guestfs_progress_cb cb, void *opaque)
+  GUESTFS_DEPRECATED_BY(\"set_event_callback\");
 
 /* Private data area. */
 #define LIBGUESTFS_HAVE_SET_PRIVATE 1
@@ -526,16 +545,23 @@ extern void *guestfs_next_private (guestfs_h *g, const char **key_rtn);
   List.iter (
     fun (shortname, (ret, args, optargs as style), _, flags, _, _, _) ->
       let deprecated =
-        List.exists (function DeprecatedBy _ -> true | _ -> false) flags in
+        try
+          Some (find_map (function DeprecatedBy fn -> Some fn | _ -> None)
+                  flags)
+        with Not_found -> None in
       let test0 =
         String.length shortname >= 5 && String.sub shortname 0 5 = "test0" in
       let debug =
         String.length shortname >= 5 && String.sub shortname 0 5 = "debug" in
-      if not deprecated && not test0 && not debug then
+      if deprecated = None && not test0 && not debug then
         pr "#define LIBGUESTFS_HAVE_%s 1\n" (String.uppercase shortname);
 
-      generate_prototype ~single_line:true ~newline:true ~handle:"g"
-        ~prefix:"guestfs_" shortname style;
+      generate_prototype ~single_line:true ~semicolon:false
+        ~handle:"g" ~prefix:"guestfs_" shortname style;
+      (match deprecated with
+       | Some fn -> pr "\n  GUESTFS_DEPRECATED_BY (%S);\n" fn
+       | None -> pr ";\n"
+      );
 
       if optargs <> [] then (
         generate_prototype ~single_line:true ~newline:true ~handle:"g"
@@ -570,6 +596,8 @@ extern void *guestfs_next_private (guestfs_h *g, const char **key_rtn);
           ~prefix:"guestfs_" ~suffix:"_argv" ~optarg_proto:Argv
           shortname style;
       );
+
+      pr "\n";
   ) all_functions_sorted;
 
   pr "\
@@ -1177,6 +1205,8 @@ trace_send_line (guestfs_h *g)
             pr "  if (r == -1) {\n";
             pr "    guestfs___end_busy (g);\n";
             trace_return_error ~indent:4 shortname style errcode;
+            pr "    /* daemon will send an error reply which we discard */\n";
+            pr "    guestfs___recv_discard (g, \"%s\");\n" shortname;
             pr "    return %s;\n" (string_of_errcode errcode);
             pr "  }\n";
             pr "  if (r == -2) /* daemon cancelled */\n";