ocaml: Error on compiler warnings.
[libguestfs.git] / generator / generator_c.ml
index 0a9060b..4480200 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
@@ -35,27 +36,41 @@ type optarg_proto = Dots | VA | Argv
 (* Generate a C function prototype. *)
 let rec generate_prototype ?(extern = true) ?(static = false)
     ?(semicolon = true)
-    ?(single_line = false) ?(newline = false) ?(in_daemon = false)
+    ?(single_line = false) ?(indent = "") ?(newline = false)
+    ?(in_daemon = false)
     ?(prefix = "") ?(suffix = "")
     ?handle
     ?(optarg_proto = Dots)
     name (ret, args, optargs) =
+  pr "%s" indent;
   if extern then pr "extern ";
   if static then pr "static ";
   (match ret with
-   | RErr -> pr "int "
-   | RInt _ -> pr "int "
-   | RInt64 _ -> pr "int64_t "
-   | RBool _ -> pr "int "
-   | RConstString _ | RConstOptString _ -> pr "const char *"
-   | RString _ | RBufferOut _ -> pr "char *"
-   | RStringList _ | RHashtable _ -> pr "char **"
+   | RErr
+   | RInt _
+   | RBool _ ->
+       pr "int";
+       if single_line then pr " " else pr "\n%s" indent
+   | RInt64 _ ->
+       pr "int64_t";
+       if single_line then pr " " else pr "\n%s" indent
+   | RConstString _ | RConstOptString _ ->
+       pr "const char *";
+       if not single_line then pr "\n%s" indent
+   | RString _ | RBufferOut _ ->
+       pr "char *";
+       if not single_line then pr "\n%s" indent
+   | RStringList _ | RHashtable _ ->
+       pr "char **";
+       if not single_line then pr "\n%s" indent
    | RStruct (_, typ) ->
        if not in_daemon then pr "struct guestfs_%s *" typ
-       else pr "guestfs_int_%s *" typ
+       else pr "guestfs_int_%s *" typ;
+       if not single_line then pr "\n%s" indent
    | RStructList (_, typ) ->
        if not in_daemon then pr "struct guestfs_%s_list *" typ
-       else pr "guestfs_int_%s_list *" typ
+       else pr "guestfs_int_%s_list *" typ;
+       if not single_line then pr "\n%s" indent
   );
   let is_RBufferOut = match ret with RBufferOut _ -> true | _ -> false in
   pr "%s%s%s (" prefix name suffix;
@@ -69,7 +84,12 @@ let rec generate_prototype ?(extern = true) ?(static = false)
     );
     let next () =
       if !comma then (
-        if single_line then pr ", " else pr ",\n\t\t"
+        if single_line then pr ", "
+        else (
+          let namelen = String.length prefix + String.length name +
+                        String.length suffix + 2 in
+          pr ",\n%s%s" indent (spaces namelen)
+        )
       );
       comma := true
     in
@@ -152,8 +172,7 @@ and generate_actions_pod () =
       if not (List.mem NotInDocs flags) then (
         let name = "guestfs_" ^ shortname in
         pr "=head2 %s\n\n" name;
-        pr " ";
-        generate_prototype ~extern:false ~handle:"g" name style;
+        generate_prototype ~extern:false ~indent:" " ~handle:"g" name style;
         pr "\n\n";
 
         let uc_shortname = String.uppercase shortname in
@@ -236,20 +255,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";
@@ -438,6 +459,7 @@ and generate_client_actions () =
 #include \"guestfs-internal.h\"
 #include \"guestfs-internal-actions.h\"
 #include \"guestfs_protocol.h\"
+#include \"errnostring.h\"
 
 /* Check the return message from a call for validity. */
 static int
@@ -590,11 +612,12 @@ check_state (guestfs_h *g, const char *caller)
       | Pathname n
       | Dev_or_Path n
       | FileIn n
-      | FileOut n
-      | BufferIn 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"
@@ -613,6 +636,9 @@ check_state (guestfs_h *g, const char *caller)
           pr "    fprintf (stderr, \" %%d\", %s);\n" n
       | Int64 n ->
           pr "    fprintf (stderr, \" %%\" PRIi64, %s);\n" n
+      | BufferIn n ->                   (* RHBZ#646822 *)
+          pr "    fputc (' ', stderr);\n";
+          pr "    guestfs___print_BufferIn (stderr, %s, %s_size);\n" n n
     ) args;
 
     (* Optional arguments. *)
@@ -800,8 +826,18 @@ check_state (guestfs_h *g, const char *caller)
       pr "\n";
 
       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
-      pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
+      pr "    int errnum = 0;\n";
+      pr "    if (err.errno_string[0] != '\\0')\n";
+      pr "      errnum = guestfs___string_to_errno (err.errno_string);\n";
+      pr "    if (errnum <= 0)\n";
+      pr "      error (g, \"%%s: %%s\", \"%s\", err.error_message);\n"
+        shortname;
+      pr "    else\n";
+      pr "      guestfs_error_errno (g, errnum, \"%%s: %%s\", \"%s\",\n"
+        shortname;
+      pr "                           err.error_message);\n";
       pr "    free (err.error_message);\n";
+      pr "    free (err.errno_string);\n";
       pr "    guestfs___end_busy (g);\n";
       pr "    return %s;\n" error_code;
       pr "  }\n";
@@ -992,6 +1028,7 @@ and generate_linker_script () =
     "guestfs_get_error_handler";
     "guestfs_get_out_of_memory_handler";
     "guestfs_get_private";
+    "guestfs_last_errno";
     "guestfs_last_error";
     "guestfs_set_close_callback";
     "guestfs_set_error_handler";