From 02b64d5cec1ac0a6f7627d5489996de4474a67f6 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Mon, 1 Sep 2025 17:00:16 +0100 Subject: [PATCH] generator: Use quoted string literals in many places This change was done almost entirely automatically using the script below. This uses the OCaml lexer to read the source files and extract the strings and locations. Strings which are "candidates" (in this case, longer than 3 lines) are replaced in the output with quoted string literals. Since the OCaml lexer is used, it already substitutes all escape sequences correctly. I diffed the output of the generator and it is identical after this change, except for UUIDs, which change because of how Utils.stable_uuid is implemented. Thanks: Nicolas Ojeda Bar $ ocamlfind opt -package unix,compiler-libs.common find_strings.ml \ -o find_strings.opt -linkpkg $ for f in $( git ls-files -- \*.ml ) ; do ./find_strings.opt $f ; done open Printf let read_whole_file path = let buf = Buffer.create 16384 in let chan = open_in path in let maxlen = 16384 in let b = Bytes.create maxlen in let rec loop () = let r = input chan b 0 maxlen in if r > 0 then ( Buffer.add_substring buf (Bytes.to_string b) 0 r; loop () ) in loop (); close_in chan; Buffer.contents buf let count_chars c str = let count = ref 0 in for i = 0 to String.length str - 1 do if c = String.unsafe_get str i then incr count done; !count let subs = ref [] let consider_string str loc = let nr_lines = count_chars '\n' str in if nr_lines > 3 then subs := (str, loc) :: !subs let () = Lexer.init (); let filename = Sys.argv.(1) in let content = read_whole_file filename in let lexbuf = Lexing.from_string content in let rec loop () = let token = Lexer.token lexbuf in (match token with | Parser.EOF -> (); | STRING (s, loc, sopt) -> consider_string s loc; (* sopt? *) loop (); | token -> loop (); ) in loop (); (* The list of subs is already reversed, which is convenient * because we must the file substitutions in reverse order. *) let subs = !subs in let new_content = ref content in List.iter ( fun (str, loc) -> let { Location.loc_start = { pos_cnum = p1 }; loc_end = { pos_cnum = p2 } } = loc in let len = String.length !new_content in let before = String.sub !new_content 0 (p1-1) in let after = String.sub !new_content (p2+1) (len - p2 - 1) in new_content := before ^ "{|" ^ str ^ "|}" ^ after ) subs; let new_content = !new_content in if content <> new_content then ( (* Update the file in place. *) let new_filename = filename ^ ".new" and backup_filename = filename ^ ".bak" in let chan = open_out new_filename in fprintf chan "%s" new_content; close_out chan; Unix.rename filename backup_filename; Unix.rename new_filename filename ) --- generator/GObject.ml | 91 +- generator/OCaml.ml | 78 +- generator/XDR.ml | 12 +- generator/actions_augeas.ml | 30 +- generator/actions_core.ml | 1414 ++++++++------------ generator/actions_core_deprecated.ml | 105 +- generator/actions_debug.ml | 10 +- generator/actions_hivex.ml | 25 +- generator/actions_hivex_deprecated.ml | 5 +- generator/actions_inspection.ml | 255 ++-- generator/actions_inspection_deprecated.ml | 30 +- generator/actions_internal_tests.ml | 35 +- generator/actions_properties.ml | 140 +- generator/actions_properties_deprecated.ml | 20 +- generator/actions_tsk.ml | 15 +- generator/actions_yara.ml | 10 +- generator/bindtests.ml | 65 +- generator/c.ml | 198 ++- generator/csharp.ml | 13 +- generator/customize.ml | 187 ++- generator/daemon.ml | 71 +- generator/docstrings.ml | 8 +- generator/erlang.ml | 45 +- generator/errnostring.ml | 43 +- generator/fish.ml | 107 +- generator/fish_commands.ml | 68 +- generator/golang.ml | 29 +- generator/haskell.ml | 20 +- generator/java.ml | 48 +- generator/lua.ml | 137 +- generator/perl.ml | 75 +- generator/php.ml | 57 +- generator/prepopts.ml | 16 +- generator/python.ml | 97 +- generator/ruby.ml | 57 +- generator/rust.ml | 6 +- generator/tests_c_api.ml | 37 +- 37 files changed, 1605 insertions(+), 2054 deletions(-) diff --git a/generator/GObject.ml b/generator/GObject.ml index 87c5b33bf..f7d872d20 100644 --- a/generator/GObject.ml +++ b/generator/GObject.ml @@ -120,23 +120,23 @@ let header_start filename = let guard = "GUESTFS_GOBJECT_" ^ String.uppercase_ascii guard ^ "_H__" in pr "#ifndef %s\n" guard; pr "#define %s\n" guard; - pr " + pr {| #include #include #include G_BEGIN_DECLS -" +|} and header_end filename = let guard = Str.global_replace (Str.regexp "-") "_" filename in let guard = "GUESTFS_GOBJECT_" ^ String.uppercase_ascii guard ^ "_H__" in - pr " + pr {| G_END_DECLS #endif /* %s */ -" guard +|} guard let source_start ?title ?shortdesc ?longdesc filename = generate_header CStyle GPLv2plus; @@ -518,7 +518,7 @@ let generate_gobject_optargs_source filename name optargs f () = let generate_gobject_tristate_header () = let filename = "tristate" in header_start filename; - pr " + pr {| /** * GuestfsTristate: * @GUESTFS_TRISTATE_FALSE: False @@ -539,7 +539,7 @@ typedef enum GType guestfs_tristate_get_type (void); #define GUESTFS_TYPE_TRISTATE (guestfs_tristate_get_type ()) -"; +|}; header_end filename let generate_gobject_tristate_source () = @@ -547,33 +547,33 @@ let generate_gobject_tristate_source () = let title = "GuestfsTristate" in let shortdesc = "An object representing a tristate value" in source_start ~title ~shortdesc filename; - pr " + pr {| GType guestfs_tristate_get_type (void) { static GType etype = 0; if (etype == 0) { static const GEnumValue values[] = { - { GUESTFS_TRISTATE_FALSE, \"GUESTFS_TRISTATE_FALSE\", \"false\" }, - { GUESTFS_TRISTATE_TRUE, \"GUESTFS_TRISTATE_TRUE\", \"true\" }, - { GUESTFS_TRISTATE_NONE, \"GUESTFS_TRISTATE_NONE\", \"none\" }, + { GUESTFS_TRISTATE_FALSE, "GUESTFS_TRISTATE_FALSE", "false" }, + { GUESTFS_TRISTATE_TRUE, "GUESTFS_TRISTATE_TRUE", "true" }, + { GUESTFS_TRISTATE_NONE, "GUESTFS_TRISTATE_NONE", "none" }, { 0, NULL, NULL } }; - etype = g_enum_register_static (\"GuestfsTristate\", values); + etype = g_enum_register_static ("GuestfsTristate", values); } return etype; } -" +|} let generate_gobject_session_header () = let filename = "session" in header_start filename; - pr " + pr {| /* GuestfsSessionEvent */ /** * GuestfsSessionEvent: -"; +|}; List.iter ( fun (name, _) -> @@ -581,18 +581,18 @@ let generate_gobject_session_header () = (String.uppercase_ascii name) name; ) events; - pr " * - * For more detail on libguestfs events, see \"SETTING CALLBACKS TO HANDLE - * EVENTS\" in guestfs(3). + pr {| * + * For more detail on libguestfs events, see "SETTING CALLBACKS TO HANDLE + * EVENTS" in guestfs(3). */ -typedef enum {"; +typedef enum {|}; List.iter ( fun (name, _) -> pr "\n GUESTFS_SESSION_EVENT_%s," (String.uppercase_ascii name); ) events; - pr " + pr {| } GuestfsSessionEvent; GType guestfs_session_event_get_type (void); #define GUESTFS_TYPE_SESSION_EVENT (guestfs_session_event_get_type ()) @@ -625,24 +625,11 @@ GType guestfs_session_event_params_get_type (void); /* GuestfsSession object definition */ #define GUESTFS_TYPE_SESSION (guestfs_session_get_type ()) -#define GUESTFS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ( \ - (obj), \ - GUESTFS_TYPE_SESSION, \ - GuestfsSession)) -#define GUESTFS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ( \ - (klass), \ - GUESTFS_TYPE_SESSION, \ - GuestfsSessionClass)) -#define GUESTFS_IS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ( \ - (obj), \ - GUESTFS_TYPE_SESSION)) -#define GUESTFS_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ( \ - (klass), \ - GUESTFS_TYPE_SESSION)) -#define GUESTFS_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ( \ - (obj), \ - GUESTFS_TYPE_SESSION, \ - GuestfsSessionClass)) +#define GUESTFS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ( (obj), GUESTFS_TYPE_SESSION, GuestfsSession)) +#define GUESTFS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ( (klass), GUESTFS_TYPE_SESSION, GuestfsSessionClass)) +#define GUESTFS_IS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ( (obj), GUESTFS_TYPE_SESSION)) +#define GUESTFS_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ( (klass), GUESTFS_TYPE_SESSION)) +#define GUESTFS_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ( (obj), GUESTFS_TYPE_SESSION, GuestfsSessionClass)) typedef struct _GuestfsSessionPrivate GuestfsSessionPrivate; @@ -674,7 +661,7 @@ GType guestfs_session_get_type (void); GuestfsSession *guestfs_session_new (void); gboolean guestfs_session_close (GuestfsSession *session, GError **err); -"; +|}; List.iter ( fun ({ name; style } as f) -> @@ -689,7 +676,7 @@ let generate_gobject_session_source () = let shortdesc = "A libguestfs session" in source_start ~shortdesc filename; - pr " + pr {| /* It is safe to call deprecated functions from this file. */ #define GUESTFS_NO_WARN_DEPRECATED #undef GUESTFS_NO_DEPRECATED @@ -709,7 +696,7 @@ let generate_gobject_session_source () = static GQuark guestfs_error_quark (void) { - return g_quark_from_static_string (\"guestfs\"); + return g_quark_from_static_string ("guestfs"); } /* Cancellation handler */ @@ -739,15 +726,15 @@ G_DEFINE_BOXED_TYPE (GuestfsSessionEventParams, guestfs_session_event_params_free) /* Event callback */ -"; +|}; pr "static guint signals[%i] = { 0 };\n" (List.length events); -pr " +pr {| static GuestfsSessionEvent guestfs_session_event_from_guestfs_event (uint64_t event) { - switch (event) {"; + switch (event) {|}; List.iter ( fun (name, _) -> @@ -756,10 +743,10 @@ guestfs_session_event_from_guestfs_event (uint64_t event) pr "\n case %s: return %s;" guestfs_name enum_name; ) events; -pr " +pr {| } - g_warning (\"guestfs_session_event_from_guestfs_event: invalid event %%\" PRIu64, + g_warning ("guestfs_session_event_from_guestfs_event: invalid event %%" PRIu64, event); return UINT32_MAX; } @@ -801,7 +788,7 @@ guestfs_session_event_get_type (void) { static GType etype = 0; if (etype == 0) { - static const GEnumValue values[] = {"; + static const GEnumValue values[] = {|}; List.iter ( fun (name, _) -> @@ -809,9 +796,9 @@ guestfs_session_event_get_type (void) pr "\n { %s, \"%s\", \"%s\" }," enum_name enum_name name ) events; - pr " + pr {| }; - etype = g_enum_register_static (\"GuestfsSessionEvent\", values); + etype = g_enum_register_static ("GuestfsSessionEvent", values); } return etype; } @@ -843,7 +830,7 @@ guestfs_session_class_init (GuestfsSessionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->finalize = guestfs_session_finalize;"; + object_class->finalize = guestfs_session_finalize;|}; List.iter ( fun (name, _) -> @@ -868,7 +855,7 @@ guestfs_session_class_init (GuestfsSessionClass *klass) pr " 1, guestfs_session_event_params_get_type ());"; ) events; - pr " + pr {| } static void @@ -912,7 +899,7 @@ guestfs_session_close (GuestfsSession *session, GError **err) guestfs_h *g = session->priv->g; if (g == NULL) { - g_set_error_literal (err, GUESTFS_ERROR, 0, \"session is already closed\"); + g_set_error_literal (err, GUESTFS_ERROR, 0, "session is already closed"); return FALSE; } @@ -920,7 +907,7 @@ guestfs_session_close (GuestfsSession *session, GError **err) session->priv->g = NULL; return TRUE; -}"; +}|}; let urls = Str.regexp "L<\\(https?\\)://\\([^>]*\\)>" in let bz = Str.regexp "RHBZ#\\([0-9]+\\)" in diff --git a/generator/OCaml.ml b/generator/OCaml.ml index d4dfe9ed0..95e4c5b97 100644 --- a/generator/OCaml.ml +++ b/generator/OCaml.ml @@ -48,8 +48,7 @@ let ocaml_errnos = [ let rec generate_ocaml_mli () = generate_header OCamlStyle LGPLv2plus; - pr "\ -(** libguestfs bindings for OCaml. + pr {|(** libguestfs bindings for OCaml. For API documentation, the canonical reference is the {{:http://libguestfs.org/guestfs.3.html}guestfs(3)} man page. @@ -98,15 +97,14 @@ val close : t -> unit (** {3 Events} *) type event = -"; +|}; List.iter ( fun (name, _) -> pr " | EVENT_%s\n" (String.uppercase_ascii name) ) events; pr "\n"; - pr "\ -val event_all : event list + pr {|val event_all : event list (** A list containing all event types. *) type event_handle @@ -149,18 +147,17 @@ val last_errno : t -> int which you can use to test the return value of {!Guestfs.last_errno}. *) module Errno : sig -"; +|}; List.iter ( fun e -> pr " val errno_%s : int\n" e; pr " (** Integer value of errno [%s]. See {!Guestfs.last_errno}. *)\n" e ) ocaml_errnos; - pr "\ -end + pr {|end (** {3 Structs} *) -"; +|}; generate_ocaml_structure_decls (); pr "\ @@ -234,8 +231,7 @@ end pr "\n"; ) (actions |> external_functions |> sort); - pr "\ -(** {2 Object-oriented API} + pr {|(** {2 Object-oriented API} This is an alternate way of calling the API using an object-oriented style, so you can use @@ -268,7 +264,7 @@ class guestfs : ?environment:bool -> ?close_on_exit:bool -> unit -> object (** See {!Guestfs.last_errno} *) method ocaml_handle : t (** Return the {!Guestfs.t} handle *) -"; +|}; List.iter ( fun ({ name; style; non_c_aliases } as f) -> @@ -306,15 +302,14 @@ class guestfs : ?environment:bool -> ?close_on_exit:bool -> unit -> object and generate_ocaml_ml () = generate_header OCamlStyle LGPLv2plus; - pr "\ -type t + pr {|type t exception Error of string exception Handle_closed of string external _create : ?environment:bool -> ?close_on_exit:bool -> unit -> t = - \"guestfs_int_ocaml_create\" -external close : t -> unit = \"guestfs_int_ocaml_close\" + "guestfs_int_ocaml_create" +external close : t -> unit = "guestfs_int_ocaml_close" let create ?environment ?close_on_exit () = let g = _create ?environment ?close_on_exit () in @@ -322,7 +317,7 @@ let create ?environment ?close_on_exit () = g type event = -"; +|}; List.iter ( fun (name, _) -> pr " | EVENT_%s\n" (String.uppercase_ascii name) @@ -337,24 +332,23 @@ let event_all = [ pr " EVENT_%s;\n" (String.uppercase_ascii name) ) events; - pr "\ -] + pr {|] type event_handle = int type event_callback = event -> event_handle -> string -> int64 array -> unit external set_event_callback : t -> event_callback -> event list -> event_handle - = \"guestfs_int_ocaml_set_event_callback\" + = "guestfs_int_ocaml_set_event_callback" external delete_event_callback : t -> event_handle -> unit - = \"guestfs_int_ocaml_delete_event_callback\" + = "guestfs_int_ocaml_delete_event_callback" external event_to_string : event list -> string - = \"guestfs_int_ocaml_event_to_string\" + = "guestfs_int_ocaml_event_to_string" -external last_errno : t -> int = \"guestfs_int_ocaml_last_errno\" +external last_errno : t -> int = "guestfs_int_ocaml_last_errno" module Errno = struct -"; +|}; List.iter ( fun e -> let le = String.lowercase_ascii e in @@ -362,15 +356,14 @@ module Errno = struct le e; pr " let errno_%s = %s ()\n" e le ) ocaml_errnos; - pr "\ -end + pr {|end (* Give the exceptions names, so they can be raised from the C code. *) let () = - Callback.register_exception \"guestfs_int_ocaml_error\" (Error \"\"); - Callback.register_exception \"guestfs_int_ocaml_closed\" (Handle_closed \"\") + Callback.register_exception "guestfs_int_ocaml_error" (Error ""); + Callback.register_exception "guestfs_int_ocaml_closed" (Handle_closed "") -"; +|}; generate_ocaml_structure_decls (); @@ -382,7 +375,7 @@ let () = ) (actions |> external_functions |> sort); (* OO API. *) - pr " + pr {| class guestfs ?environment ?close_on_exit () = let g = create ?environment ?close_on_exit () in object (self) @@ -391,7 +384,7 @@ class guestfs ?environment ?close_on_exit () = method delete_event_callback = delete_event_callback g method last_errno () = last_errno g method ocaml_handle = g -"; +|}; List.iter ( fun { name; style; non_c_aliases } -> @@ -415,8 +408,7 @@ class guestfs ?environment ?close_on_exit () = and generate_ocaml_c () = generate_header CStyle LGPLv2plus; - pr "\ -#include + pr {|#include /* It is safe to call deprecated functions from this file. */ #define GUESTFS_NO_WARN_DEPRECATED @@ -437,9 +429,9 @@ and generate_ocaml_c () = #include #include -#include \"guestfs-utils.h\" +#include "guestfs-utils.h" -#include \"guestfs-c.h\" +#include "guestfs-c.h" /* Copy a hashtable of string pairs into an assoc-list. We return * the list in reverse order, but hashtables aren't supposed to be @@ -468,7 +460,7 @@ copy_table (char * const * argv) CAMLreturn (rv); } -"; +|}; (* Struct copy functions. *) @@ -795,8 +787,7 @@ copy_table (char * const * argv) and generate_ocaml_c_errnos () = generate_header CStyle LGPLv2plus; - pr "\ -#include + pr {|#include #include #include @@ -809,12 +800,12 @@ and generate_ocaml_c_errnos () = #include #include -#include \"guestfs.h\" +#include "guestfs.h" -#include \"guestfs-c.h\" +#include "guestfs-c.h" /* These prototypes are solely to quiet gcc warnings. */ -"; +|}; List.iter ( fun e -> pr "value guestfs_int_ocaml_get_%s (value unitv);\n" e @@ -822,15 +813,14 @@ and generate_ocaml_c_errnos () = List.iter ( fun e -> - pr "\ - + pr {| /* NB: [@@noalloc] function. */ value guestfs_int_ocaml_get_%s (value unitv) { return Val_int (%s); } -" e e +|} e e ) ocaml_errnos and generate_ocaml_structure_decls () = diff --git a/generator/XDR.ml b/generator/XDR.ml index 431959819..c79f7c6c9 100644 --- a/generator/XDR.ml +++ b/generator/XDR.ml @@ -189,8 +189,7 @@ let generate_xdr () = pr "\n"; (* Message header, etc. *) - pr "\ -const GUESTFS_PROGRAM = 0x2000F5F5; + pr {|const GUESTFS_PROGRAM = 0x2000F5F5; const GUESTFS_PROTOCOL_VERSION = 4; /* These constants must be larger than any possible message length. */ @@ -208,14 +207,13 @@ enum guestfs_message_status { GUESTFS_STATUS_ERROR = 1 }; -"; +|}; pr "const GUESTFS_ERROR_LEN = %d;\n" (64 * 1024); pr "\n"; - pr "\ -struct guestfs_message_error { - string errno_string<32>; /* errno eg. \"EINVAL\", empty string + pr {|struct guestfs_message_error { + string errno_string<32>; /* errno eg. "EINVAL", empty string if errno not available */ string error_message; }; @@ -261,4 +259,4 @@ struct guestfs_progress { uint64_t total; /* @16: total size of operation */ /* @24: size of structure */ }; -" +|} diff --git a/generator/actions_augeas.ml b/generator/actions_augeas.ml index 9688c7ca4..d28d4f40b 100644 --- a/generator/actions_augeas.ml +++ b/generator/actions_augeas.ml @@ -34,8 +34,7 @@ let daemon_functions = [ ["aug_get"; "/files/etc/hostname/hostname"]], "test.example.org"), [["aug_close"]] ]; shortdesc = "create a new Augeas handle"; - longdesc = "\ -Create a new Augeas handle for editing configuration files. + longdesc = {|Create a new Augeas handle for editing configuration files. If there was any previous Augeas handle associated with this guestfs session, then it is closed. @@ -85,7 +84,7 @@ Do not load the tree in C. To close the handle, you can call C. -To find out more about Augeas, see L." }; +To find out more about Augeas, see L.|} }; { defaults with name = "aug_close"; added = (0, 0, 7); @@ -101,20 +100,18 @@ Augeas functions." }; name = "aug_defvar"; added = (0, 0, 7); style = RInt "nrnodes", [String (PlainString, "name"); OptString "expr"], []; shortdesc = "define an Augeas variable"; - longdesc = "\ -Defines an Augeas variable C whose value is the result + longdesc = {|Defines an Augeas variable C whose value is the result of evaluating C. If C is NULL, then C is undefined. On success this returns the number of nodes in C, or -C<0> if C evaluates to something which is not a nodeset." }; +C<0> if C evaluates to something which is not a nodeset.|} }; { defaults with name = "aug_defnode"; added = (0, 0, 7); style = RStruct ("nrnodescreated", "int_bool"), [String (PlainString, "name"); String (PlainString, "expr"); String (PlainString, "val")], []; shortdesc = "define an Augeas node"; - longdesc = "\ -Defines a variable C whose value is the result of + longdesc = {|Defines a variable C whose value is the result of evaluating C. If C evaluates to an empty nodeset, a node is created, @@ -123,7 +120,7 @@ C will be the nodeset containing that single node. On success this returns a pair containing the number of nodes in the nodeset, and a boolean flag -if a node was created." }; +if a node was created.|} }; { defaults with name = "aug_get"; added = (0, 0, 7); @@ -145,13 +142,12 @@ matches exactly one node, the C is returned." }; ["aug_get"; "/files/etc/hostname/hostname"]], "replace.example.com"), [["aug_close"]] ]; shortdesc = "set Augeas path to value"; - longdesc = "\ -Set the value associated with C to C. + longdesc = {|Set the value associated with C to C. In the Augeas API, it is possible to clear a node by setting the value to NULL. Due to an oversight in the libguestfs API you cannot do that with this call. Instead you must use the -C call." }; +C call.|} }; { defaults with name = "aug_insert"; added = (0, 0, 7); @@ -170,14 +166,13 @@ C call." }; ["cat"; "/etc/hosts"]], "\n127.0.0.1\tlocalhost\n"), [["aug_close"]] ]; shortdesc = "insert a sibling Augeas node"; - longdesc = "\ -Create a new sibling C