Add Erlang bindings.
[libguestfs.git] / generator / generator_utils.ml
index 2bdcc0d..4180c0d 100644 (file)
@@ -1,5 +1,5 @@
 (* libguestfs
- * Copyright (C) 2009-2010 Red Hat Inc.
+ * Copyright (C) 2009-2011 Red Hat Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,6 +28,21 @@ open Printf
 
 open Generator_types
 
+let errcode_of_ret = function
+  | RConstOptString _ ->
+      `CannotReturnError
+  | RErr | RInt _ | RBool _ | RInt64 _ ->
+      `ErrorIsMinusOne
+  | RConstString _
+  | RString _ | RBufferOut _
+  | RStringList _ | RHashtable _
+  | RStruct _ | RStructList _ ->
+      `ErrorIsNULL
+
+let string_of_errcode = function
+  | `ErrorIsMinusOne -> "-1"
+  | `ErrorIsNULL -> "NULL"
+
 (* Generate a uuidgen-compatible UUID (used in tests).  However to
  * avoid having the UUID change every time we rebuild the tests,
  * generate it as a function of the contents of the
@@ -40,6 +55,14 @@ open Generator_types
  *)
 let uuidgen () =
   let s = Digest.to_hex (Digest.file "generator/generator_actions.ml") in
+
+  (* In util-linux <= 2.19, mkswap -U cannot handle the first byte of
+   * the UUID being zero, so we artificially rewrite such UUIDs.
+   * http://article.gmane.org/gmane.linux.utilities.util-linux-ng/4273
+   *)
+  if s.[0] = '0' && s.[1] = '0' then
+    s.[0] <- '1';
+
   String.sub s 0 8 ^ "-"
   ^ String.sub s 8 4 ^ "-"
   ^ String.sub s 12 4 ^ "-"
@@ -83,8 +106,8 @@ let rstructs_used_by functions =
   in
 
   List.iter (
-    fun (_, style, _, _, _, _, _) ->
-      match fst style with
+    fun (_, (ret, _, _), _, _, _, _, _) ->
+      match ret with
       | RStruct (_, structname) -> update structname RStructOnly
       | RStructList (_, structname) -> update structname RStructListOnly
       | _ -> ()
@@ -230,7 +253,7 @@ let map_chars f str =
 let name_of_argt = function
   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
   | StringList n | DeviceList n | Bool n | Int n | Int64 n
-  | FileIn n | FileOut n | BufferIn n | Key n -> n
+  | FileIn n | FileOut n | BufferIn n | Key n | Pointer (_, n) -> n
 
 let seq_of_test = function
   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
@@ -244,15 +267,17 @@ let seq_of_test = function
   | TestLastFail s -> s
 
 let c_quote str =
+  let str = replace_str str "\\" "\\\\" in
   let str = replace_str str "\r" "\\r" in
   let str = replace_str str "\n" "\\n" in
   let str = replace_str str "\t" "\\t" in
   let str = replace_str str "\000" "\\0" in
+  let str = replace_str str "\"" "\\\"" in
   str
 
 (* Used to memoize the result of pod2text. *)
-let pod2text_memo_filename = "generator/.pod2text.data"
-let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
+let pod2text_memo_filename = "generator/.pod2text.data.version.2"
+let pod2text_memo : ((int option * bool * bool * string * string), string list) Hashtbl.t =
   try
     let chan = open_in pod2text_memo_filename in
     let v = input_value chan in
@@ -271,22 +296,27 @@ let pod2text_memo_updated () =
  * Because this is very slow (the slowest part of autogeneration),
  * we memoize the results.
  *)
-let pod2text ~width name longdesc =
-  let key = width, name, longdesc in
+let pod2text ?width ?(trim = true) ?(discard = true) name longdesc =
+  let key = width, trim, discard, name, longdesc in
   try Hashtbl.find pod2text_memo key
   with Not_found ->
     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
     close_out chan;
-    let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
+    let cmd =
+      match width with
+      | Some width ->
+          sprintf "pod2text -w %d %s" width (Filename.quote filename)
+      | None ->
+          sprintf "pod2text %s" (Filename.quote filename) in
     let chan = open_process_in cmd in
     let lines = ref [] in
     let rec loop i =
       let line = input_line chan in
-      if i = 1 then            (* discard the first line of output *)
+      if i = 1 && discard then  (* discard the first line of output *)
         loop (i+1)
       else (
-        let line = triml line in
+        let line = if trim then triml line else line in
         lines := line :: !lines;
         loop (i+1)
       ) in
@@ -303,3 +333,14 @@ let pod2text ~width name longdesc =
     pod2text_memo_updated ();
     lines
 
+(* Compare two actions (for sorting). *)
+let action_compare (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) = compare n1 n2
+
+let chars c n =
+  let str = String.create n in
+  for i = 0 to n-1 do
+    String.unsafe_set str i c
+  done;
+  str
+
+let spaces n = chars ' ' n