Laszlo Ersek
2023-May-10 11:48 UTC
[Libguestfs] [libnbd PATCH 2/6] generator/utils: add "pr_wrap_c_comment"
Add the "pr_wrap_c_comment" function, for wrapping C comments. Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2172516 Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- generator/utils.mli | 1 + generator/utils.ml | 87 ++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/generator/utils.mli b/generator/utils.mli index 9d6640c87842..e622e318c2b7 100644 --- a/generator/utils.mli +++ b/generator/utils.mli @@ -54,6 +54,7 @@ val 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 pr_wrap_c_comment : ?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 ff1e8a72f7aa..8f9ce8a84910 100644 --- a/generator/utils.ml +++ b/generator/utils.ml @@ -267,6 +267,93 @@ let ) fields | _ -> assert false +(* Wrap a string as a (potentially multi-line) C comment. Two things to note: + * - the function produces both the starting slash-star and the ending + * star-slash, + * - newline characters in the input are not allowed. + *) +let pr_wrap_c_comment ?(maxcol = 80) code + (* The comment delimiters. *) + let start = "/* " + and sep = " * " + and stop = " */" + + (* Format the comment into a buffer, and append a space character, for forcing + * a nonspace -> space transiton at the end of the comment, provided the + * comment ends with a nonspace. Note that trailing spaces will be swallowed + * anyway, as only nonspace -> space transitions produce output. + *) + and comment = pr_buf (fun () -> code (); pr " ") + + (* Capture the current column / indentation. *) + and indent = spaces !col + + (* Whether we're currently scanning spaces. We start the loop under the + * assumption "scanning spaces" because a space -> nonspace transition does + * not try to output anything. + *) + and scanning_spaces = ref true + + (* The "buffers" for accumulating spaces and nonspaces. *) + and spaces_start = ref 0 + and nonspaces_start = ref 0 + + (* Whether we've needed to insert at least one line break. *) + and multiline = ref false in + + pr "%s" start; + + for i = 0 to Buffer.length comment - 1 do + let ch = Buffer.nth comment i in + + (* Newlines are invalid... *) + assert (ch <> '\n'); + + match !scanning_spaces, ch with + | true, ' ' -> + () + | true, _ -> + (* Space -> nonspace transition. *) + scanning_spaces := false; + nonspaces_start := i + | false, ' ' -> + (* Nonspace -> space transition. If the buffered spaces: + * + * nonspaces_start - spaces_start + * + * plus the buffered nonspaces: + * + * i - nonspaces_start + * + * fit on the current line, then print both buffers. (Note that the sum + * of those addends is just (i - spaces_start).) + * + * Otherwise, insert a line break and a comment line separator, and only + * print the nonspaces. + *) + if !col + (i - !spaces_start) <= maxcol then + pr "%s" (Buffer.sub comment !spaces_start (i - !spaces_start)) + else ( + pr "\n%s%s%s" indent sep + (Buffer.sub comment !nonspaces_start (i - !nonspaces_start)); + multiline := true + ); + + scanning_spaces := true; + spaces_start := i + | false, _ -> + () + done; + + (* If the comment has fit on a single line, and we've got room left for the + * terminator, then place the terminator on the same line. Otherwise, break + * the terminator to a new line. + *) + if not !multiline && !col + String.length stop <= maxcol then + pr "%s" stop + else + pr "\n%s%s" indent stop + let output_lineno () = !lineno let output_column () = !col
Eric Blake
2023-May-10 15:08 UTC
[Libguestfs] [libnbd PATCH 2/6] generator/utils: add "pr_wrap_c_comment"
On Wed, May 10, 2023 at 01:48:10PM +0200, Laszlo Ersek wrote:> Add the "pr_wrap_c_comment" function, for wrapping C comments. > > Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2172516 > Signed-off-by: Laszlo Ersek <lersek at redhat.com> > --- > generator/utils.mli | 1 + > generator/utils.ml | 87 ++++++++++++++++++++ > 2 files changed, 88 insertions(+) >> +++ b/generator/utils.ml> + > + (* Format the comment into a buffer, and append a space character, for forcing > + * a nonspace -> space transiton at the end of the comment, provided thetransition Otherwise, well-commented, and looks like it meets the intent. Reviewed-by: Eric Blake <eblake at redhat.com> -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org