Add the "pr_wrap_cstr" function, for wrapping C string literals.

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2172516
Signed-off-by: Laszlo Ersek <ler...@redhat.com>
---
 generator/utils.mli |  1 +
 generator/utils.ml  | 54 ++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/generator/utils.mli b/generator/utils.mli
index 5bbb188fe934..9d6640c87842 100644
--- a/generator/utils.mli
+++ b/generator/utils.mli
@@ -53,6 +53,7 @@ val
 val output_to : string -> (unit -> 'a) -> unit
 val pr : ('a, unit, string, unit) format4 -> 'a
 val pr_wrap : ?maxcol:int -> char -> (unit -> 'a) -> unit
+val pr_wrap_cstr : ?maxcol:int -> (unit -> 'a) -> unit
 val output_lineno : unit -> int
 val output_column : unit -> int
 
diff --git a/generator/utils.ml b/generator/utils.ml
index 919572b73557..ff1e8a72f7aa 100644
--- a/generator/utils.ml
+++ b/generator/utils.ml
@@ -213,6 +213,60 @@ let
       *)
      pr "%s" (String.concat "\n" rest)
 
+(* Wrap the C string literal output at ‘maxcol’, breaking up lines when a space
+ * character occurs.  For example:
+ *   foobar = "a b c d e f g h i j k"
+ *             └── pr_wrap_cstr ───┘
+ * becomes:
+ *   foobar = "a b c d "
+ *            "e f g h "
+ *            "i j k"
+ *
+ * Note that:
+ * - ‘code’ MUST NOT produce the surrounding quotes,
+ * - ‘code’ MUST NOT produce multiple lines,
+ * - ‘code’ MUST do its own quoting,
+ * - space characters produced by ‘code’ cannot be escaped from wrapping.
+ *)
+let pr_wrap_cstr ?(maxcol = 76) code =
+  (* Just before entering ‘pr_wrap_cstr’, a leading quote must have been
+   * produced.
+   *)
+  let wrapping_col = !col - 1 in
+  assert (wrapping_col >= 0);
+
+  let b = pr_buf code in
+  let lines = nsplit "\n" (Buffer.contents b) in
+  match lines with
+  | [] -> ()
+  | line :: [] ->
+     let fields = nsplit " " line in
+     let nfields = List.length fields in
+     let indent = spaces wrapping_col in
+     List.iteri
+       (fun i field ->
+          (* Append a space character to each field except the last. *)
+          let f = if i < nfields - 1 then field ^ " " else field in
+
+          (* Terminate the string literal, insert a line break, and start a
+           * properly indented new string literal, before printing the field, 
if
+           * (a) the field is not the first one in this string literal, and (b)
+           * printing the field plus a literal-terminating quote would not fit
+           * in ‘maxcol’.
+           *
+           * Note that this way, the literal-terminating quote will always fit
+           * in ‘maxcol’, except when the *sole* field in the literal is too
+           * long.
+           *)
+          if !col > wrapping_col + 1 &&
+             !col + (String.length f) + 1 > maxcol then
+            pr "\"\n%s\"" indent;
+
+          (* Print the field. *)
+          pr "%s" f
+       ) fields
+  | _ -> assert false
+
 let output_lineno () = !lineno
 let output_column () = !col
 

_______________________________________________
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to