Richard W.M. Jones
2016-Dec-08 10:36 UTC
[Libguestfs] [PATCH] generator: Share Common_utils code.
For a very long time we have maintained two sets of utility functions, in mllib/common_utils.ml and generator/utils.ml. This changes things so that the same set of utility functions can be shared with both directories. It's not possible to use common_utils.ml directly in the generator because it provides several functions that use modules outside the OCaml stdlib. Therefore we add some lightweight post-processing which extracts the functions using only the stdlib: (*<stdlib>*) ... (*</stdlib>*) and creates generator/common_utils.ml and generator/common_utils.mli from that. The effect is we only need to write utility functions once. As with other tools, we still have generator-specific utility functions in generator/utils.ml. Also in this change: - Use String.uppercase_ascii and String.lowercase_ascii in place of deprecated String.uppercase/String.lowercase. - Implement String.capitalize_ascii to replace deprecated String.capitalize. - Move isspace, isdigit, isxdigit functions to Char module. --- .gitignore | 3 + dib/utils.ml | 2 +- generator/Makefile.am | 23 ++++++- generator/bindtests.ml | 25 +++---- generator/c.ml | 53 ++++++++------- generator/daemon.ml | 10 +-- generator/docstrings.ml | 3 +- generator/erlang.ml | 23 ++++--- generator/events.ml | 1 + generator/fish.ml | 34 +++++----- generator/gobject.ml | 32 +++++---- generator/java.ml | 8 ++- generator/lua.ml | 3 +- generator/ocaml.ml | 11 +-- generator/perl.ml | 11 +-- generator/pr.ml | 3 +- generator/python.ml | 25 +++---- generator/ruby.ml | 11 +-- generator/tests_c_api.ml | 13 ++-- generator/uefi.ml | 1 + generator/utils.ml | 173 ++++------------------------------------------- generator/utils.mli | 64 +----------------- mllib/common_utils.ml | 126 ++++++++++++++++++++++++++++++---- mllib/common_utils.mli | 76 ++++++++++++++++++--- v2v/convert_windows.ml | 3 +- 25 files changed, 373 insertions(+), 364 deletions(-) diff --git a/.gitignore b/.gitignore index 633b39d..da59e44 100644 --- a/.gitignore +++ b/.gitignore @@ -255,8 +255,11 @@ Makefile.in /fuse/test-guestunmount-fd /generator/.depend /generator/bytes.ml +/generator/common_utils.ml +/generator/common_utils.mli /generator/files-generated.txt /generator/generator +/generator/guestfs_config.ml /generator/.pod2text.data* /generator/stamp-generator /get-kernel/.depend diff --git a/dib/utils.ml b/dib/utils.ml index 3df5171..4026ee8 100644 --- a/dib/utils.ml +++ b/dib/utils.ml @@ -74,7 +74,7 @@ let digit_prefix_compare a b let split_prefix str let len = String.length str in let digits - try string_index_fn (fun x -> not (isdigit x)) str + try string_index_fn (fun x -> not (Char.isdigit x)) str with Not_found -> len in match digits with | 0 -> "", str diff --git a/generator/Makefile.am b/generator/Makefile.am index 31c33fa..0c2ae33 100644 --- a/generator/Makefile.am +++ b/generator/Makefile.am @@ -27,6 +27,8 @@ sources = \ c.mli \ checks.ml \ checks.mli \ + common_utils.ml \ + common_utils.mli \ csharp.ml \ csharp.mli \ customize.ml \ @@ -47,6 +49,7 @@ sources = \ gobject.mli \ golang.ml \ golang.mli \ + guestfs_config.ml \ haskell.ml \ haskell.mli \ java.ml \ @@ -85,6 +88,8 @@ sources = \ # In build dependency order. objects = \ $(OCAML_GENERATOR_BYTES_COMPAT_CMO) \ + guestfs_config.cmo \ + common_utils.cmo \ types.cmo \ utils.cmo \ actions.cmo \ @@ -133,7 +138,7 @@ generator: $(objects) # Dependencies. depend: .depend -.depend: $(wildcard $(abs_srcdir)/*.mli) $(wildcard $(abs_srcdir)/*.ml) +.depend: $(wildcard $(abs_srcdir)/*.mli) $(wildcard $(abs_srcdir)/*.ml) common_utils.ml common_utils.mli guestfs_config.ml rm -f $@ $@-t $(OCAMLFIND) ocamldep -I ../ocaml -I $(abs_srcdir) $^ | \ $(SED) 's/ *$$//' | \ @@ -174,6 +179,22 @@ stamp-generator: generator cd $(top_srcdir) && $(abs_builddir)/generator touch $@ +# We share common_utils.ml{,i} with the mllib directory. However we +# have to remove functions which depend on any modules which are not +# part of the OCaml stdlib. +common_utils.ml: $(top_srcdir)/mllib/common_utils.ml + rm -f $@ $@-t + echo '(* This file is generated from mllib/common_utils.ml *)' > $@-t + sed -n '/^(\*<stdlib>\*)$$/,/^(\*<\/stdlib>\*)$$/p' $< >> $@-t + mv $@-t $@ +common_utils.mli: $(top_srcdir)/mllib/common_utils.mli + rm -f $@ $@-t + echo '(* This file is generated from mllib/common_utils.mli *)' > $@-t + sed -n '/^(\*<stdlib>\*)$$/,/^(\*<\/stdlib>\*)$$/p' $< >> $@-t + mv $@-t $@ +guestfs_config.ml: ../mllib/guestfs_config.ml + cp $< $@ + CLEANFILES += $(noinst_DATA) $(noinst_PROGRAM) DISTCLEANFILES += .pod2text.data.version.2 diff --git a/generator/bindtests.ml b/generator/bindtests.ml index 742cb1b..ffb3ee7 100644 --- a/generator/bindtests.ml +++ b/generator/bindtests.ml @@ -20,6 +20,7 @@ open Printf +open Common_utils open Types open Utils open Pr @@ -176,7 +177,7 @@ fill_lvm_pv (guestfs_h *g, struct guestfs_lvm_pv *pv, size_t i) let check_optarg n printf_args pr " fprintf (fp, \"%s: \");\n" n; pr " if (optargs->bitmask & %s_%s_BITMASK) {\n" c_optarg_prefix - (String.uppercase n); + (String.uppercase_ascii n); pr " fprintf (fp, %s);\n" printf_args; pr " } else {\n"; pr " fprintf (fp, \"unset\\n\");\n"; @@ -200,7 +201,7 @@ fill_lvm_pv (guestfs_h *g, struct guestfs_lvm_pv *pv, size_t i) | OStringList n -> pr " fprintf (fp, \"%s: \");\n" n; pr " if (optargs->bitmask & %s_%s_BITMASK) {\n" c_optarg_prefix - (String.uppercase n); + (String.uppercase_ascii n); pr " print_strings (g, optargs->%s);\n" n; pr " } else {\n"; pr " fprintf (fp, \"unset\\n\");\n"; @@ -583,7 +584,7 @@ public class Bindtests { | CallBool b -> string_of_bool b | CallBuffer s -> "new byte[] { " ^ String.concat "," ( - map_chars (fun c -> string_of_int (Char.code c)) s + String.map_chars (fun c -> string_of_int (Char.code c)) s ) ^ " }" ) args ) @@ -845,7 +846,7 @@ and generate_golang_bindtests () generate_lang_bindtests ( fun f args optargs -> - pr " if err := g.%s (" (String.capitalize f); + pr " if err := g.%s (" (String.capitalize_ascii f); let needs_comma = ref false in List.iter ( @@ -869,13 +870,13 @@ and generate_golang_bindtests () | c -> sprintf "'%c'" c in pr "[]byte{%s}" - (String.concat ", " (List.map quote_char (explode s))) + (String.concat ", " (List.map quote_char (String.explode s))) ) args; if !needs_comma then pr ", "; (match optargs with | None -> pr "nil" | Some optargs -> - pr "&guestfs.Optargs%s{" (String.capitalize f); + pr "&guestfs.Optargs%s{" (String.capitalize_ascii f); needs_comma := false; List.iter ( fun optarg -> @@ -883,19 +884,19 @@ and generate_golang_bindtests () needs_comma := true; match optarg with | CallOBool (n, v) -> - let n = String.capitalize n in + let n = String.capitalize_ascii n in pr "%s_is_set: true, %s: %b" n n v | CallOInt (n, v) -> - let n = String.capitalize n in + let n = String.capitalize_ascii n in pr "%s_is_set: true, %s: %d" n n v | CallOInt64 (n, v) -> - let n = String.capitalize n in + let n = String.capitalize_ascii n in pr "%s_is_set: true, %s: %Ld" n n v | CallOString (n, v) -> - let n = String.capitalize n in + let n = String.capitalize_ascii n in pr "%s_is_set: true, %s: \"%s\"" n n v | CallOStringList (n, xs) -> - let n = String.capitalize n in + let n = String.capitalize_ascii n in pr "%s_is_set: true, %s: []string{%s}" n n (String.concat ", " (List.map (sprintf "\"%s\"") xs)) ) optargs; @@ -971,7 +972,7 @@ and generate_php_bindtests () let chan = open_in filename in let rec loop () let line = input_line chan in - (match string_split ":" line with + (match String.nsplit ":" line with | ("obool"|"oint"|"oint64"|"ostring"|"ostringlist") as x :: _ -> pr "%s: unset\n" x | _ -> pr "%s\n" line diff --git a/generator/c.ml b/generator/c.ml index 6f5a517..79d3811 100644 --- a/generator/c.ml +++ b/generator/c.ml @@ -20,6 +20,7 @@ open Printf +open Common_utils open Types open Utils open Pr @@ -102,7 +103,7 @@ let rec generate_prototype ?(extern = true) ?(static = false) else ( let namelen = String.length prefix + String.length name + String.length suffix + 2 in - pr ",\n%s%s" indent (spaces namelen) + pr ",\n%s%s" indent (String.spaces namelen) ) ); comma := true @@ -230,7 +231,8 @@ and generate_actions_pod_entry ({ c_name = c_name; List.iter ( fun argt -> let n = name_of_optargt argt in - pr " GUESTFS_%s_%s, " (String.uppercase c_name) (String.uppercase n); + pr " GUESTFS_%s_%s, " (String.uppercase_ascii c_name) + (String.uppercase_ascii n); match argt with | OBool n -> pr "int %s,\n" n | OInt n -> pr "int %s,\n" n @@ -508,7 +510,7 @@ extern GUESTFS_DLL_PUBLIC guestfs_abort_cb guestfs_get_out_of_memory_handler (gu List.iter ( fun (name, bitmask) -> pr "#define GUESTFS_EVENT_%-16s 0x%04x\n" - (String.uppercase name) bitmask + (String.uppercase_ascii name) bitmask ) events; pr "#define GUESTFS_EVENT_%-16s 0x%04x\n" "ALL" all_events_bitmask; pr "\n"; @@ -601,7 +603,7 @@ extern GUESTFS_DLL_PUBLIC void *guestfs_next_private (guestfs_h *g, const char * (* Public structures. *) let generate_all_structs = List.iter ( fun { s_name = typ; s_cols = cols } -> - pr "#define GUESTFS_HAVE_STRUCT_%s 1\n" (String.uppercase typ); + pr "#define GUESTFS_HAVE_STRUCT_%s 1\n" (String.uppercase_ascii typ); pr "\n"; pr "struct guestfs_%s {\n" typ; List.iter ( @@ -645,14 +647,14 @@ extern GUESTFS_DLL_PUBLIC void *guestfs_next_private (guestfs_h *g, const char * let generate_action_header { name = shortname; style = ret, args, optargs as style; deprecated_by = deprecated_by } - pr "#define GUESTFS_HAVE_%s 1\n" (String.uppercase shortname); + pr "#define GUESTFS_HAVE_%s 1\n" (String.uppercase_ascii shortname); if optargs <> [] then ( iteri ( fun i argt -> - let uc_shortname = String.uppercase shortname in + let uc_shortname = String.uppercase_ascii shortname in let n = name_of_optargt argt in - let uc_n = String.uppercase n in + let uc_n = String.uppercase_ascii n in pr "#define GUESTFS_%s_%s %d\n" uc_shortname uc_n i; ) optargs; ); @@ -682,9 +684,9 @@ extern GUESTFS_DLL_PUBLIC void *guestfs_next_private (guestfs_h *g, const char * | OInt64 n -> "int64_t " | OString n -> "const char *" | OStringList n -> "char *const *" in - let uc_shortname = String.uppercase shortname in + let uc_shortname = String.uppercase_ascii shortname in let n = name_of_optargt argt in - let uc_n = String.uppercase n in + let uc_n = String.uppercase_ascii n in pr "# define GUESTFS_%s_%s_BITMASK (UINT64_C(1)<<%d)\n" uc_shortname uc_n i; pr " %s%s;\n" c_type n ) optargs; @@ -759,7 +761,7 @@ pr "\ List.iter ( fun { name = shortname } -> - pr "#define LIBGUESTFS_HAVE_%s 1\n" (String.uppercase shortname); + pr "#define LIBGUESTFS_HAVE_%s 1\n" (String.uppercase_ascii shortname); ) public_functions_sorted; pr " @@ -810,9 +812,9 @@ and generate_internal_frontend_cleanups_h () List.iter ( fun { s_name = name } -> - pr "#define CLEANUP_FREE_%s \\\n" (String.uppercase name); + pr "#define CLEANUP_FREE_%s \\\n" (String.uppercase_ascii name); pr " __attribute__((cleanup(guestfs_int_cleanup_free_%s)))\n" name; - pr "#define CLEANUP_FREE_%s_LIST \\\n" (String.uppercase name); + pr "#define CLEANUP_FREE_%s_LIST \\\n" (String.uppercase_ascii name); pr " __attribute__((cleanup(guestfs_int_cleanup_free_%s_list)))\n" name ) structs; @@ -820,8 +822,8 @@ and generate_internal_frontend_cleanups_h () List.iter ( fun { s_name = name } -> - pr "#define CLEANUP_FREE_%s\n" (String.uppercase name); - pr "#define CLEANUP_FREE_%s_LIST\n" (String.uppercase name) + pr "#define CLEANUP_FREE_%s\n" (String.uppercase_ascii name); + pr "#define CLEANUP_FREE_%s_LIST\n" (String.uppercase_ascii name) ) structs; pr "\ @@ -1409,7 +1411,7 @@ and generate_client_actions actions () function | OString n -> pr " if ((optargs->bitmask & GUESTFS_%s_%s_BITMASK) &&\n" - (String.uppercase c_name) (String.uppercase n); + (String.uppercase_ascii c_name) (String.uppercase_ascii n); pr " optargs->%s == NULL) {\n" n; pr " error (g, \"%%s: %%s: optional parameter cannot be NULL\",\n"; pr " \"%s\", \"%s\");\n" c_name n; @@ -1423,7 +1425,7 @@ and generate_client_actions actions () | OStringList n -> pr " if ((optargs->bitmask & GUESTFS_%s_%s_BITMASK) &&\n" - (String.uppercase c_name) (String.uppercase n); + (String.uppercase_ascii c_name) (String.uppercase_ascii n); pr " optargs->%s == NULL) {\n" n; pr " error (g, \"%%s: %%s: optional list cannot be NULL\",\n"; pr " \"%s\", \"%s\");\n" c_name n; @@ -1587,7 +1589,7 @@ and generate_client_actions actions () fun argt -> let n = name_of_optargt argt in pr " if (optargs->bitmask & GUESTFS_%s_%s_BITMASK) {\n" - (String.uppercase c_name) (String.uppercase n); + (String.uppercase_ascii c_name) (String.uppercase_ascii n); (match argt with | OString n -> pr " fprintf (trace_buffer.fp, \" \\\"%%s:%%s\\\"\", \"%s\", optargs->%s);\n" n n @@ -1614,7 +1616,7 @@ and generate_client_actions actions () in let trace_return ?(indent = 2) name (ret, _, _) rv - let indent = spaces indent in + let indent = String.spaces indent in pr "%sif (trace_flag) {\n" indent; @@ -1679,7 +1681,7 @@ and generate_client_actions actions () in let trace_return_error ?(indent = 2) name (ret, _, _) errcode - let indent = spaces indent in + let indent = String.spaces indent in pr "%sif (trace_flag)\n" indent; @@ -1876,7 +1878,7 @@ and generate_client_actions actions () (* Send the main header and arguments. *) if args_passed_to_daemon = [] && optargs = [] then ( pr " serial = guestfs_int_send (g, GUESTFS_PROC_%s, progress_hint, 0,\n" - (String.uppercase name); + (String.uppercase_ascii name); pr " NULL, NULL);\n" ) else ( List.iter ( @@ -1913,7 +1915,7 @@ and generate_client_actions actions () fun argt -> let n = name_of_optargt argt in pr " if (optargs->bitmask & GUESTFS_%s_%s_BITMASK) {\n" - (String.uppercase c_name) (String.uppercase n); + (String.uppercase_ascii c_name) (String.uppercase_ascii n); (match argt with | OBool n | OInt n @@ -1938,7 +1940,7 @@ and generate_client_actions actions () ) optargs; pr " serial = guestfs_int_send (g, GUESTFS_PROC_%s,\n" - (String.uppercase name); + (String.uppercase_ascii name); pr " progress_hint, %s,\n" (if optargs <> [] then "optargs->bitmask" else "0"); pr " (xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n" @@ -1989,7 +1991,7 @@ and generate_client_actions actions () pr "\n"; pr " if (guestfs_int_check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n" - (String.uppercase name); + (String.uppercase_ascii name); trace_return_error ~indent:4 name style errcode; pr " return %s;\n" (string_of_errcode errcode); pr " }\n"; @@ -2160,7 +2162,7 @@ and generate_client_actions_variants () fun argt -> let n = name_of_optargt argt in pr " case GUESTFS_%s_%s:\n" - (String.uppercase c_name) (String.uppercase n); + (String.uppercase_ascii c_name) (String.uppercase_ascii n); pr " optargs_s.%s = va_arg (args, " n; (match argt with | OBool _ | OInt _ -> pr "int" @@ -2273,7 +2275,8 @@ guestfs_event_to_string (uint64_t event) List.iter ( fun name -> - pr " if ((event & GUESTFS_EVENT_%s) != 0) {\n" (String.uppercase name); + pr " if ((event & GUESTFS_EVENT_%s) != 0) {\n" + (String.uppercase_ascii name); pr " strcpy (&ret[len], \"%s,\");\n" name; pr " len += %d + 1;\n" (String.length name); pr " }\n"; diff --git a/generator/daemon.ml b/generator/daemon.ml index ce5dada..f05d5b7 100644 --- a/generator/daemon.ml +++ b/generator/daemon.ml @@ -20,6 +20,7 @@ open Printf +open Common_utils open Types open Utils open Pr @@ -49,9 +50,9 @@ let generate_daemon_actions_h () | { name = shortname; style = _, _, (_::_ as optargs) } -> iteri ( fun i arg -> - let uc_shortname = String.uppercase shortname in + let uc_shortname = String.uppercase_ascii shortname in let n = name_of_optargt arg in - let uc_n = String.uppercase n in + let uc_n = String.uppercase_ascii n in pr "#define GUESTFS_%s_%s_BITMASK (UINT64_C(1)<<%d)\n" uc_shortname uc_n i ) optargs @@ -541,7 +542,7 @@ let generate_daemon_dispatch () List.iter ( fun { name = name } -> - pr " case GUESTFS_PROC_%s:\n" (String.uppercase name); + pr " case GUESTFS_PROC_%s:\n" (String.uppercase_ascii name); pr " %s_stub (xdr_in);\n" name; pr " break;\n" ) (actions |> daemon_functions); @@ -819,7 +820,8 @@ let generate_daemon_optgroups_h () "; List.iter ( fun (group, fns) -> - pr "#define OPTGROUP_%s_NOT_AVAILABLE \\\n" (String.uppercase group); + pr "#define OPTGROUP_%s_NOT_AVAILABLE \\\n" + (String.uppercase_ascii group); List.iter ( fun { name = name; style = ret, args, optargs } -> let style = ret, args @ args_of_optargs optargs, [] in diff --git a/generator/docstrings.ml b/generator/docstrings.ml index 9d3fd0b..845ec63 100644 --- a/generator/docstrings.ml +++ b/generator/docstrings.ml @@ -21,6 +21,7 @@ open Unix open Printf +open Common_utils open Types open Utils open Pr @@ -41,7 +42,7 @@ let deprecation_notice ?(prefix = "") ?(replace_underscores = false) | { deprecated_by = None } -> None | { deprecated_by = Some alt } -> let alt - if replace_underscores then replace_char alt '_' '-' else alt in + if replace_underscores then String.replace_char alt '_' '-' else alt in let txt sprintf "I<This function is deprecated.> In new code, use the L</%s%s> call instead. diff --git a/generator/erlang.ml b/generator/erlang.ml index fab92a0..3753835 100644 --- a/generator/erlang.ml +++ b/generator/erlang.ml @@ -20,6 +20,7 @@ open Printf +open Common_utils open Types open Utils open Pr @@ -105,7 +106,7 @@ loop(Port) -> pr "%s(G" name; List.iter ( fun arg -> - pr ", %s" (String.capitalize (name_of_argt arg)) + pr ", %s" (String.capitalize_ascii (name_of_argt arg)) ) args; if optargs <> [] then pr ", Optargs"; @@ -114,7 +115,7 @@ loop(Port) -> pr " call_port(G, {%s" name; List.iter ( fun arg -> - pr ", %s" (String.capitalize (name_of_argt arg)) + pr ", %s" (String.capitalize_ascii (name_of_argt arg)) ) args; if optargs <> [] then pr ", Optargs"; @@ -128,14 +129,14 @@ loop(Port) -> pr "%s(G" name; List.iter ( fun arg -> - pr ", %s" (String.capitalize (name_of_argt arg)) + pr ", %s" (String.capitalize_ascii (name_of_argt arg)) ) args; pr ") ->\n"; pr " %s(G" name; List.iter ( fun arg -> - pr ", %s" (String.capitalize (name_of_argt arg)) + pr ", %s" (String.capitalize_ascii (name_of_argt arg)) ) args; pr ", []"; pr ").\n" @@ -147,7 +148,7 @@ loop(Port) -> pr "%s(G" alias; List.iter ( fun arg -> - pr ", %s" (String.capitalize (name_of_argt arg)) + pr ", %s" (String.capitalize_ascii (name_of_argt arg)) ) args; if optargs <> [] then pr ", Optargs"; @@ -156,7 +157,7 @@ loop(Port) -> pr " %s(G" name; List.iter ( fun arg -> - pr ", %s" (String.capitalize (name_of_argt arg)) + pr ", %s" (String.capitalize_ascii (name_of_argt arg)) ) args; if optargs <> [] then pr ", Optargs"; @@ -166,14 +167,14 @@ loop(Port) -> pr "%s(G" alias; List.iter ( fun arg -> - pr ", %s" (String.capitalize (name_of_argt arg)) + pr ", %s" (String.capitalize_ascii (name_of_argt arg)) ) args; pr ") ->\n"; pr " %s(G" name; List.iter ( fun arg -> - pr ", %s" (String.capitalize (name_of_argt arg)) + pr ", %s" (String.capitalize_ascii (name_of_argt arg)) ) args; pr ").\n" ) @@ -404,7 +405,7 @@ instead of erl_interface. List.iter ( fun argt -> let n = name_of_optargt argt in - let uc_n = String.uppercase n in + let uc_n = String.uppercase_ascii n in pr " if (atom_equals (hd_name, \"%s\")) {\n" n; pr " optargs_s.bitmask |= %s_%s_BITMASK;\n" c_optarg_prefix uc_n; @@ -457,12 +458,12 @@ instead of erl_interface. function | OBool _ | OInt _ | OInt64 _ -> () | OString n -> - let uc_n = String.uppercase n in + let uc_n = String.uppercase_ascii n in pr " if ((optargs_s.bitmask & %s_%s_BITMASK))\n" c_optarg_prefix uc_n; pr " free ((char *) optargs_s.%s);\n" n | OStringList n -> - let uc_n = String.uppercase n in + let uc_n = String.uppercase_ascii n in pr " if ((optargs_s.bitmask & %s_%s_BITMASK))\n" c_optarg_prefix uc_n; pr " guestfs_int_free_string_list ((char **) optargs_s.%s);\n" n diff --git a/generator/events.ml b/generator/events.ml index c92c760..7188e12 100644 --- a/generator/events.ml +++ b/generator/events.ml @@ -18,6 +18,7 @@ (* Please read generator/README first. *) +open Common_utils open Utils (* NB: DO NOT REORDER THESE, as doing so will change the ABI. Only diff --git a/generator/fish.ml b/generator/fish.ml index 62752e8..9ef7a30 100644 --- a/generator/fish.ml +++ b/generator/fish.ml @@ -20,6 +20,7 @@ open Printf +open Common_utils open Types open Utils open Pr @@ -53,7 +54,7 @@ let doc_opttype_of = function let get_aliases { fish_alias = fish_alias; non_c_aliases = non_c_aliases } let non_c_aliases - List.map (fun n -> replace_char n '_' '-') non_c_aliases in + List.map (fun n -> String.replace_char n '_' '-') non_c_aliases in fish_alias @ non_c_aliases let all_functions_commands_and_aliases_sorted @@ -73,7 +74,7 @@ let all_functions_commands_and_aliases_sorted let c_quoted_indented ~indent str let str = c_quote str in - let str = replace_str str "\\n" ("\\n\"\n" ^ indent ^ "\"") in + let str = String.replace str "\\n" ("\\n\"\n" ^ indent ^ "\"") in str (* Generate run_* functions and header for libguestfs API functions. *) @@ -322,7 +323,7 @@ let generate_fish_run_cmds actions () List.iter ( fun argt -> let n = name_of_optargt argt in - let uc_n = String.uppercase n in + let uc_n = String.uppercase_ascii n in let len = String.length n in pr "if (STRPREFIX (argv[i], \"%s:\")) {\n" n; (match argt with @@ -466,7 +467,7 @@ let generate_fish_run_cmds actions () List.iter ( function | OStringList n -> - let uc_n = String.uppercase n in + let uc_n = String.uppercase_ascii n in pr " if ((optargs_s.bitmask & %s_%s_BITMASK) &&\n" c_optarg_prefix uc_n; pr " optargs_s.%s != NULL)\n" n; @@ -539,9 +540,9 @@ let generate_fish_cmd_entries actions () shortdesc = shortdesc; longdesc = longdesc } as f) -> let aliases = get_aliases f in - let name2 = replace_char name '_' '-' in + let name2 = String.replace_char name '_' '-' in - let longdesc = replace_str longdesc "C<guestfs_" "C<" in + let longdesc = String.replace longdesc "C<guestfs_" "C<" in let synopsis match args with | [] -> name2 @@ -625,7 +626,7 @@ let generate_fish_cmds () fun ({ name = name; shortdesc = shortdesc; longdesc = longdesc } as f) -> let aliases = get_aliases f in - let name2 = replace_char name '_' '-' in + let name2 = String.replace_char name '_' '-' in let describe_alias if aliases <> [] then sprintf "\n\nYou can use %s as an alias for this command." @@ -656,13 +657,13 @@ let generate_fish_cmds () pr " list_builtin_commands ();\n"; List.iter ( fun (name, f) -> - let name = replace_char name '_' '-' in + let name = String.replace_char name '_' '-' in match f with | Function shortdesc -> pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n" name shortdesc | Alias f -> - let f = replace_char f '_' '-' in + let f = String.replace_char f '_' '-' in pr " printf (\"%%-20s \", \"%s\");\n" name; pr " printf (_(\"alias for '%%s'\"), \"%s\");\n" f; pr " putchar ('\\n');\n" @@ -771,7 +772,7 @@ struct command_table; List.iter ( fun ({ name = name } as f) -> let aliases = get_aliases f in - let name2 = replace_char name '_' '-' in + let name2 = String.replace_char name '_' '-' in (* The basic command. *) pr "%s, &%s_cmd_entry\n" name name; @@ -817,7 +818,7 @@ static const char *const commands[] = { List.map ( fun ({ name = name } as f) -> let aliases = get_aliases f in - let name2 = replace_char name '_' '-' in + let name2 = String.replace_char name '_' '-' in name2 :: aliases ) (fish_functions_and_commands_sorted) in let commands = List.flatten commands in @@ -894,9 +895,9 @@ and generate_fish_actions_pod () try Str.matched_group 1 s with Not_found -> failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in - "L</" ^ replace_char sub '_' '-' ^ ">" + "L</" ^ String.replace_char sub '_' '-' ^ ">" ) longdesc in - let name = replace_char name '_' '-' in + let name = String.replace_char name '_' '-' in List.iter ( fun name -> @@ -961,7 +962,7 @@ and generate_fish_commands_pod () List.iter ( fun ({ name = name; longdesc = longdesc } as f) -> let aliases = get_aliases f in - let name = replace_char name '_' '-' in + let name = String.replace_char name '_' '-' in List.iter ( fun name -> @@ -1127,7 +1128,8 @@ event_bitmask_of_event_set (const char *arg, uint64_t *eventset_r) List.iter ( fun (name, _) -> pr "if (STREQLEN (arg, \"%s\", n))\n" name; - pr " *eventset_r |= GUESTFS_EVENT_%s;\n" (String.uppercase name); + pr " *eventset_r |= GUESTFS_EVENT_%s;\n" + (String.uppercase_ascii name); pr " else "; ) events; @@ -1166,7 +1168,7 @@ $VG guestfish \\ fun i (name, _, _, _) -> let params = [name] in let params - if find name "lv" <> -1 then ( + if String.find name "lv" <> -1 then ( incr vg_count; sprintf "/dev/VG%d/LV" !vg_count :: params ) else params in diff --git a/generator/gobject.ml b/generator/gobject.ml index 7ee73a6..e14ea20 100644 --- a/generator/gobject.ml +++ b/generator/gobject.ml @@ -22,6 +22,7 @@ open Printf +open Common_utils open Actions open Docstrings open Events @@ -125,7 +126,7 @@ let filenames let header_start filename generate_header CStyle GPLv2plus; let guard = Str.global_replace (Str.regexp "-") "_" filename in - let guard = "GUESTFS_GOBJECT_" ^ String.uppercase guard ^ "_H__" in + let guard = "GUESTFS_GOBJECT_" ^ String.uppercase_ascii guard ^ "_H__" in pr "#ifndef %s\n" guard; pr "#define %s\n" guard; pr " @@ -139,7 +140,7 @@ G_BEGIN_DECLS and header_end filename let guard = Str.global_replace (Str.regexp "-") "_" filename in - let guard = "GUESTFS_GOBJECT_" ^ String.uppercase guard ^ "_H__" in + let guard = "GUESTFS_GOBJECT_" ^ String.uppercase_ascii guard ^ "_H__" in pr " G_END_DECLS @@ -299,7 +300,7 @@ let generate_gobject_struct_source filename typ () let generate_gobject_optargs_header filename name f () header_start filename; - let uc_name = String.uppercase name in + let uc_name = String.uppercase_ascii name in let camel_name = camel_of_name f in let type_define = "GUESTFS_TYPE_" ^ uc_name in @@ -358,7 +359,7 @@ let generate_gobject_optargs_source filename name optargs f () "An object encapsulating optional arguments for guestfs_session_" ^ name in source_start ~shortdesc:desc ~longdesc:desc filename; - let uc_name = String.uppercase name in + let uc_name = String.uppercase_ascii name in let camel_name = camel_of_name f in let type_define = "GUESTFS_TYPE_" ^ uc_name in @@ -386,7 +387,7 @@ let generate_gobject_optargs_source filename name optargs f () pr " PROP_GUESTFS_%s_PROP0" uc_name; List.iter ( fun optargt -> - let uc_optname = String.uppercase (name_of_optargt optargt) in + let uc_optname = String.uppercase_ascii (name_of_optargt optargt) in pr ",\n PROP_GUESTFS_%s_%s" uc_name uc_optname; ) optargs; pr "\n};\n\n"; @@ -402,7 +403,7 @@ let generate_gobject_optargs_source filename name optargs f () function OStringList _ -> () (* XXX *) | optargt -> let optname = name_of_optargt optargt in - let uc_optname = String.uppercase optname in + let uc_optname = String.uppercase_ascii optname in pr " case PROP_GUESTFS_%s_%s:\n" uc_name uc_optname; (match optargt with | OString n -> @@ -435,7 +436,7 @@ let generate_gobject_optargs_source filename name optargs f () function OStringList _ -> () (* XXX *) | optargt -> let optname = name_of_optargt optargt in - let uc_optname = String.uppercase optname in + let uc_optname = String.uppercase_ascii optname in pr " case PROP_GUESTFS_%s_%s:\n" uc_name uc_optname; let set_value_func = match optargt with | OBool _ -> "enum" @@ -508,7 +509,7 @@ let generate_gobject_optargs_source filename name optargs f () pr " */\n"; pr " g_object_class_install_property (\n"; pr " object_class,\n"; - pr " PROP_GUESTFS_%s_%s,\n" uc_name (String.uppercase optname); + pr " PROP_GUESTFS_%s_%s,\n" uc_name (String.uppercase_ascii optname); pr " g_param_spec_%s (\n" type_spec; pr " \"%s\",\n" optname; pr " \"%s\",\n" optname; @@ -607,7 +608,7 @@ let generate_gobject_session_header () List.iter ( fun (name, _) -> pr " * @GUESTFS_SESSION_EVENT_%s: The %s event\n" - (String.uppercase name) name; + (String.uppercase_ascii name) name; ) events; pr " * @@ -618,7 +619,7 @@ typedef enum {"; List.iter ( fun (name, _) -> - pr "\n GUESTFS_SESSION_EVENT_%s," (String.uppercase name); + pr "\n GUESTFS_SESSION_EVENT_%s," (String.uppercase_ascii name); ) events; pr " @@ -776,8 +777,8 @@ guestfs_session_event_from_guestfs_event (uint64_t event) List.iter ( fun (name, _) -> - let enum_name = "GUESTFS_SESSION_EVENT_" ^ String.uppercase name in - let guestfs_name = "GUESTFS_EVENT_" ^ String.uppercase name in + let enum_name = "GUESTFS_SESSION_EVENT_" ^ String.uppercase_ascii name in + let guestfs_name = "GUESTFS_EVENT_" ^ String.uppercase_ascii name in pr "\n case %s: return %s;" guestfs_name enum_name; ) events; @@ -830,7 +831,7 @@ guestfs_session_event_get_type (void) List.iter ( fun (name, _) -> - let enum_name = "GUESTFS_SESSION_EVENT_" ^ String.uppercase name in + let enum_name = "GUESTFS_SESSION_EVENT_" ^ String.uppercase_ascii name in pr "\n { %s, \"%s\", \"%s\" }," enum_name enum_name name ) events; @@ -887,7 +888,8 @@ guestfs_session_class_init (GuestfsSessionClass *klass) pr " * See \"SETTING CALLBACKS TO HANDLE EVENTS\" in guestfs(3) for\n"; pr " * more details about this event.\n"; pr " */\n"; - pr " signals[GUESTFS_SESSION_EVENT_%s] =\n" (String.uppercase name); + pr " signals[GUESTFS_SESSION_EVENT_%s] =\n" + (String.uppercase_ascii name); pr " g_signal_new (g_intern_static_string (\"%s\"),\n" name; pr " G_OBJECT_CLASS_TYPE (object_class),\n"; pr " G_SIGNAL_RUN_LAST,\n"; @@ -1156,7 +1158,7 @@ guestfs_session_close (GuestfsSession *session, GError **err) pr " if (optargs) {\n"; pr " argv.bitmask = 0;\n\n"; let set_property name typ v_typ get_typ unset - let uc_name = String.uppercase name in + let uc_name = String.uppercase_ascii name in pr " GValue %s_v = {0, };\n" name; pr " g_value_init (&%s_v, %s);\n" name v_typ; pr " g_object_get_property (G_OBJECT (optargs), \"%s\", &%s_v);\n" name name; diff --git a/generator/java.ml b/generator/java.ml index 260e28c..a68054c 100644 --- a/generator/java.ml +++ b/generator/java.ml @@ -20,6 +20,7 @@ open Printf +open Common_utils open Types open Utils open Pr @@ -156,7 +157,8 @@ public class GuestFS { pr " *\n"; pr " * @see #set_event_callback\n"; pr " */\n"; - pr " public static final long EVENT_%s = 0x%x;\n" (String.uppercase name) bitmask; + pr " public static final long EVENT_%s = 0x%x;\n" + (String.uppercase_ascii name) bitmask; pr "\n"; ) events; @@ -259,7 +261,7 @@ public class GuestFS { let ret, args, optargs = f.style in if is_documented f then ( - let doc = replace_str f.longdesc "C<guestfs_" "C<g." in + let doc = String.replace f.longdesc "C<guestfs_" "C<g." in let doc if optargs <> [] then doc ^ "\n\nOptional arguments are supplied in the final Map<String,Object> parameter, which is a hash of the argument name to its value (cast to Object). Pass an empty Map or null for no optional arguments." @@ -625,7 +627,7 @@ throw_out_of_memory (JNIEnv *env, const char *msg) ); pr "JNICALL\n"; pr "Java_com_redhat_et_libguestfs_GuestFS_"; - pr "%s" (replace_str ("_" ^ name) "_" "_1"); + pr "%s" (String.replace ("_" ^ name) "_" "_1"); pr " (JNIEnv *env, jobject obj, jlong jg"; List.iter ( function diff --git a/generator/lua.ml b/generator/lua.ml index d3b0b27..e48bb3e 100644 --- a/generator/lua.ml +++ b/generator/lua.ml @@ -20,6 +20,7 @@ open Printf +open Common_utils open Types open Utils open Pr @@ -529,7 +530,7 @@ guestfs_int_lua_delete_event_callback (lua_State *L) List.iter ( fun optarg -> let n = name_of_optargt optarg in - let uc_n = String.uppercase n in + let uc_n = String.uppercase_ascii n in pr " OPTARG_IF_SET (%d, \"%s\",\n" optarg_index n; pr " optargs_s.bitmask |= %s_%s_BITMASK;\n" c_optarg_prefix uc_n; diff --git a/generator/ocaml.ml b/generator/ocaml.ml index f76a3ab..5a85d38 100644 --- a/generator/ocaml.ml +++ b/generator/ocaml.ml @@ -20,6 +20,7 @@ open Printf +open Common_utils open Types open Utils open Pr @@ -98,7 +99,7 @@ type event "; List.iter ( fun (name, _) -> - pr " | EVENT_%s\n" (String.uppercase name) + pr " | EVENT_%s\n" (String.uppercase_ascii name) ) events; pr "\n"; @@ -310,7 +311,7 @@ type event "; List.iter ( fun (name, _) -> - pr " | EVENT_%s\n" (String.uppercase name) + pr " | EVENT_%s\n" (String.uppercase_ascii name) ) events; pr "\n"; @@ -319,7 +320,7 @@ let event_all = [ "; List.iter ( fun (name, _) -> - pr " EVENT_%s;\n" (String.uppercase name) + pr " EVENT_%s;\n" (String.uppercase_ascii name) ) events; pr "\ @@ -342,7 +343,7 @@ module Errno = struct "; List.iter ( fun e -> - let le = String.lowercase e in + let le = String.lowercase_ascii e in pr " external %s : unit -> int = \"guestfs_int_ocaml_get_%s\" \"noalloc\"\n" le e; pr " let errno_%s = %s ()\n" e le @@ -637,7 +638,7 @@ copy_table (char * const * argv) List.iter ( fun argt -> let n = name_of_optargt argt in - let uc_n = String.uppercase n in + let uc_n = String.uppercase_ascii n in pr " if (%sv != Val_int (0)) {\n" n; pr " optargs_s.bitmask |= %s_%s_BITMASK;\n" c_optarg_prefix uc_n; (match argt with diff --git a/generator/perl.ml b/generator/perl.ml index 94d7c4f..290b687 100644 --- a/generator/perl.ml +++ b/generator/perl.ml @@ -20,6 +20,7 @@ open Printf +open Common_utils open Types open Utils open Pr @@ -455,7 +456,7 @@ PREINIT: List.iter ( fun argt -> let n = name_of_optargt argt in - let uc_n = String.uppercase n in + let uc_n = String.uppercase_ascii n in pr "if (STREQ (this_arg, \"%s\")) {\n" n; (match argt with | OBool _ @@ -787,14 +788,14 @@ when the final reference is cleaned up is OK). List.iter ( fun (name, bitmask) -> - pr "=item $Sys::Guestfs::EVENT_%s\n" (String.uppercase name); + pr "=item $Sys::Guestfs::EVENT_%s\n" (String.uppercase_ascii name); pr "\n"; pr "See L<guestfs(3)/GUESTFS_EVENT_%s>.\n" - (String.uppercase name); + (String.uppercase_ascii name); pr "\n"; pr "=cut\n"; pr "\n"; - pr "our $EVENT_%s = 0x%x;\n" (String.uppercase name) bitmask; + pr "our $EVENT_%s = 0x%x;\n" (String.uppercase_ascii name) bitmask; pr "\n" ) events; @@ -888,7 +889,7 @@ errnos: List.iter ( fun ({ name = name; style = style; longdesc = longdesc; non_c_aliases = non_c_aliases } as f) -> - let longdesc = replace_str longdesc "C<guestfs_" "C<$g-E<gt>" in + let longdesc = String.replace longdesc "C<guestfs_" "C<$g-E<gt>" in pr "=item "; generate_perl_prototype name style; pr "\n\n"; diff --git a/generator/pr.ml b/generator/pr.ml index 616e6f9..666cd41 100644 --- a/generator/pr.ml +++ b/generator/pr.ml @@ -21,6 +21,7 @@ open Unix open Printf +open Common_utils open Utils (* Output channel, 'pr' prints to this. *) @@ -39,7 +40,7 @@ let fileshash = Hashtbl.create 13 let pr fs ksprintf (fun str -> - let i = count_chars '\n' str in + let i = String.count_chars '\n' str in lines := !lines + i; output_string !chan str ) fs diff --git a/generator/python.ml b/generator/python.ml index 281fb0a..1e24a59 100644 --- a/generator/python.ml +++ b/generator/python.ml @@ -20,6 +20,7 @@ open Printf +open Common_utils open Types open Utils open Pr @@ -94,14 +95,14 @@ extern PyObject *guestfs_int_py_put_table (char * const * const argv); "; let emit_put_list_decl typ - pr "#ifdef GUESTFS_HAVE_STRUCT_%s\n" (String.uppercase typ); + pr "#ifdef GUESTFS_HAVE_STRUCT_%s\n" (String.uppercase_ascii typ); pr "extern PyObject *guestfs_int_py_put_%s_list (struct guestfs_%s_list *%ss);\n" typ typ typ; pr "#endif\n"; in List.iter ( fun { s_name = typ } -> - pr "#ifdef GUESTFS_HAVE_STRUCT_%s\n" (String.uppercase typ); + pr "#ifdef GUESTFS_HAVE_STRUCT_%s\n" (String.uppercase_ascii typ); pr "extern PyObject *guestfs_int_py_put_%s (struct guestfs_%s *%s);\n" typ typ typ; pr "#endif\n"; ) external_structs; @@ -118,7 +119,7 @@ extern PyObject *guestfs_int_py_put_table (char * const * const argv); List.iter ( fun { name = name; c_name = c_name } -> - pr "#ifdef GUESTFS_HAVE_%s\n" (String.uppercase c_name); + pr "#ifdef GUESTFS_HAVE_%s\n" (String.uppercase_ascii c_name); pr "extern PyObject *guestfs_int_py_%s (PyObject *self, PyObject *args);\n" name; pr "#endif\n" ) (actions |> external_functions |> sort); @@ -147,7 +148,7 @@ and generate_python_structs () "; let emit_put_list_function typ - pr "#ifdef GUESTFS_HAVE_STRUCT_%s\n" (String.uppercase typ); + pr "#ifdef GUESTFS_HAVE_STRUCT_%s\n" (String.uppercase_ascii typ); pr "PyObject *\n"; pr "guestfs_int_py_put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ; pr "{\n"; @@ -166,7 +167,7 @@ and generate_python_structs () (* Structures, turned into Python dictionaries. *) List.iter ( fun { s_name = typ; s_cols = cols } -> - pr "#ifdef GUESTFS_HAVE_STRUCT_%s\n" (String.uppercase typ); + pr "#ifdef GUESTFS_HAVE_STRUCT_%s\n" (String.uppercase_ascii typ); pr "PyObject *\n"; pr "guestfs_int_py_put_%s (struct guestfs_%s *%s)\n" typ typ typ; pr "{\n"; @@ -279,7 +280,7 @@ and generate_python_actions actions () blocking = blocking; c_name = c_name; c_function = c_function; c_optarg_prefix = c_optarg_prefix } -> - pr "#ifdef GUESTFS_HAVE_%s\n" (String.uppercase c_name); + pr "#ifdef GUESTFS_HAVE_%s\n" (String.uppercase_ascii c_name); pr "PyObject *\n"; pr "guestfs_int_py_%s (PyObject *self, PyObject *args)\n" name; pr "{\n"; @@ -415,7 +416,7 @@ and generate_python_actions actions () List.iter ( fun optarg -> let n = name_of_optargt optarg in - let uc_n = String.uppercase n in + let uc_n = String.uppercase_ascii n in pr "#ifdef %s_%s_BITMASK\n" c_optarg_prefix uc_n; pr " if (py_%s != Py_None) {\n" n; pr " optargs_s.bitmask |= %s_%s_BITMASK;\n" c_optarg_prefix uc_n; @@ -560,7 +561,7 @@ and generate_python_actions actions () function | OBool _ | OInt _ | OInt64 _ | OString _ -> () | OStringList n -> - let uc_n = String.uppercase n in + let uc_n = String.uppercase_ascii n in pr "#ifdef %s_%s_BITMASK\n" c_optarg_prefix uc_n; pr " if (py_%s != Py_None && (optargs_s.bitmask & %s_%s_BITMASK) != 0)\n" n c_optarg_prefix uc_n; @@ -606,7 +607,7 @@ and generate_python_module () pr " guestfs_int_py_event_to_string, METH_VARARGS, NULL },\n"; List.iter ( fun { name = name; c_name = c_name } -> - pr "#ifdef GUESTFS_HAVE_%s\n" (String.uppercase c_name); + pr "#ifdef GUESTFS_HAVE_%s\n" (String.uppercase_ascii c_name); pr " { (char *) \"%s\", guestfs_int_py_%s, METH_VARARGS, NULL },\n" name name; pr "#endif\n" @@ -732,7 +733,7 @@ import libguestfsmod List.iter ( fun (name, bitmask) -> - pr "EVENT_%s = 0x%x\n" (String.uppercase name) bitmask + pr "EVENT_%s = 0x%x\n" (String.uppercase_ascii name) bitmask ) events; pr "EVENT_ALL = 0x%x\n" all_events_bitmask; pr "\n"; @@ -855,7 +856,7 @@ class GuestFS(object): f.name (indent_python decl_string (9 + len_name) 78); if is_documented f then ( - let doc = replace_str f.longdesc "C<guestfs_" "C<g." in + let doc = String.replace f.longdesc "C<guestfs_" "C<g." in let doc match ret with | RErr | RInt _ | RInt64 _ | RBool _ @@ -883,7 +884,7 @@ class GuestFS(object): | Some opt -> doc ^ sprintf "\n\nThis function depends on the feature C<%s>. See also C<g.feature-available>." opt in let doc = pod2text ~width:60 f.name doc in - let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in + let doc = List.map (fun line -> String.replace line "\\" "\\\\") doc in let doc match doc with | [] -> "" diff --git a/generator/ruby.ml b/generator/ruby.ml index 74d206f..0b7cbed 100644 --- a/generator/ruby.ml +++ b/generator/ruby.ml @@ -20,6 +20,7 @@ open Printf +open Common_utils open Types open Utils open Pr @@ -127,7 +128,7 @@ and generate_ruby_c actions () (* Generate rdoc. *) if is_documented f then ( - let doc = replace_str f.longdesc "C<guestfs_" "C<g." in + let doc = String.replace f.longdesc "C<guestfs_" "C<g." in let doc if optargs <> [] then doc ^ "\n\nOptional arguments are supplied in the final hash parameter, which is a hash of the argument name to its value. Pass an empty {} for no optional arguments." @@ -138,7 +139,7 @@ and generate_ruby_c actions () else doc in let doc = pod2text ~width:60 f.name doc in let doc = String.concat "\n * " doc in - let doc = trim doc in + let doc = String.trim doc in let doc match version_added f with | None -> doc @@ -157,7 +158,7 @@ and generate_ruby_c actions () (* Because Ruby documentation appears as C comments, we must * replace any instance of "/*". *) - let doc = replace_str doc "/*" "/ *" in + let doc = String.replace doc "/*" "/ *" in let args = List.map name_of_argt args in let args = if optargs <> [] then args @ ["{optargs...}"] else args in @@ -295,7 +296,7 @@ and generate_ruby_c actions () List.iter ( fun argt -> let n = name_of_optargt argt in - let uc_n = String.uppercase n in + let uc_n = String.uppercase_ascii n in pr " v = rb_hash_lookup (optargsv, ID2SYM (rb_intern (\"%s\")));\n" n; pr " if (v != Qnil) {\n"; (match argt with @@ -483,7 +484,7 @@ Init__guestfs (void) List.iter ( fun (name, bitmask) -> pr " rb_define_const (m_guestfs, \"EVENT_%s\",\n" - (String.uppercase name); + (String.uppercase_ascii name); pr " ULL2NUM (UINT64_C (0x%x)));\n" bitmask; ) events; pr " rb_define_const (m_guestfs, \"EVENT_ALL\",\n"; diff --git a/generator/tests_c_api.ml b/generator/tests_c_api.ml index 21ef6e3..8b98927 100644 --- a/generator/tests_c_api.ml +++ b/generator/tests_c_api.ml @@ -20,6 +20,7 @@ open Printf +open Common_utils open Types open Utils open Pr @@ -201,7 +202,9 @@ static int return 0; } -" test_name name (String.uppercase test_name) (String.uppercase name); +" test_name name + (String.uppercase_ascii test_name) + (String.uppercase_ascii name); if not_disabled then ( generate_test_perform name i test_name test; @@ -441,7 +444,7 @@ and generate_test_command_call ?(expect_error = false) ?(do_return = true) ?test | StringList _, arg, sym | DeviceList _, arg, sym | FilenameList _, arg, sym -> - let strs = string_split " " arg in + let strs = String.nsplit " " arg in iteri ( fun i str -> pr " const char *%s_%d = \"%s\";\n" sym i (c_quote str); @@ -489,7 +492,7 @@ and generate_test_command_call ?(expect_error = false) ?(do_return = true) ?test | OStringList n, "" -> pr " const char *const %s[1] = { NULL };\n" n; true | OStringList n, arg -> - let strs = string_split " " arg in + let strs = String.nsplit " " arg in iteri ( fun i str -> pr " const char *%s_%d = \"%s\";\n" n i (c_quote str); @@ -519,10 +522,10 @@ and generate_test_command_call ?(expect_error = false) ?(do_return = true) ?test pr " CLEANUP_FREE_STRING_LIST char **%s;\n" ret; | RStruct (_, typ) -> pr " CLEANUP_FREE_%s struct guestfs_%s *%s;\n" - (String.uppercase typ) typ ret + (String.uppercase_ascii typ) typ ret | RStructList (_, typ) -> pr " CLEANUP_FREE_%s_LIST struct guestfs_%s_list *%s;\n" - (String.uppercase typ) typ ret + (String.uppercase_ascii typ) typ ret | RBufferOut _ -> pr " CLEANUP_FREE char *%s;\n" ret; pr " size_t size;\n" diff --git a/generator/uefi.ml b/generator/uefi.ml index 88e54b8..80b8739 100644 --- a/generator/uefi.ml +++ b/generator/uefi.ml @@ -18,6 +18,7 @@ (* Please read generator/README first. *) +open Common_utils open Utils open Pr open Docstrings diff --git a/generator/utils.ml b/generator/utils.ml index 3e81433..ba5e045 100644 --- a/generator/utils.ml +++ b/generator/utils.ml @@ -23,6 +23,8 @@ * makes this a bit harder than it should be. *) +open Common_utils + open Unix open Printf @@ -119,85 +121,6 @@ let rstructs_used_by functions let failwithf fs = ksprintf failwith fs -let unique = let i = ref 0 in fun () -> incr i; !i - -let replace_char s c1 c2 - let b2 = Bytes.of_string s in - let r = ref false in - for i = 0 to Bytes.length b2 - 1 do - if Bytes.unsafe_get b2 i = c1 then ( - Bytes.unsafe_set b2 i c2; - r := true - ) - done; - if not !r then s else Bytes.to_string b2 - -let isspace c - c = ' ' - (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *) - -let triml ?(test = isspace) str - let i = ref 0 in - let n = ref (String.length str) in - while !n > 0 && test str.[!i]; do - decr n; - incr i - done; - if !i = 0 then str - else String.sub str !i !n - -let trimr ?(test = isspace) str - let n = ref (String.length str) in - while !n > 0 && test str.[!n-1]; do - decr n - done; - if !n = String.length str then str - else String.sub str 0 !n - -let trim ?(test = isspace) str - trimr ~test (triml ~test str) - -let rec find s sub - let len = String.length s in - let sublen = String.length sub in - let rec loop i - if i <= len-sublen then ( - let rec loop2 j - if j < sublen then ( - if s.[i+j] = sub.[j] then loop2 (j+1) - else -1 - ) else - i (* found *) - in - let r = loop2 0 in - if r = -1 then loop (i+1) else r - ) else - -1 (* not found *) - in - loop 0 - -let rec replace_str s s1 s2 - let len = String.length s in - let sublen = String.length s1 in - let i = find s s1 in - if i = -1 then s - else ( - let s' = String.sub s 0 i in - let s'' = String.sub s (i+sublen) (len-i-sublen) in - s' ^ s2 ^ replace_str s'' s1 s2 - ) - -let rec string_split sep str - let len = String.length str in - let seplen = String.length sep in - let i = find str sep in - if i = -1 then [str] - else ( - let s' = String.sub str 0 i in - let s'' = String.sub str (i+seplen) (len-i-seplen) in - s' :: string_split sep s'' - ) - let files_equal n1 n2 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in match Sys.command cmd with @@ -205,70 +128,6 @@ let files_equal n1 n2 | 1 -> false | i -> failwithf "%s: failed with error code %d" cmd i -let (|>) x f = f x - -let rec filter_map f = function - | [] -> [] - | x :: xs -> - match f x with - | Some y -> y :: filter_map f xs - | None -> filter_map f xs - -let rec find_map f = function - | [] -> raise Not_found - | x :: xs -> - match f x with - | Some y -> y - | None -> find_map f xs - -let iteri f xs - let rec loop i = function - | [] -> () - | x :: xs -> f i x; loop (i+1) xs - in - loop 0 xs - -let mapi f xs - let rec loop i = function - | [] -> [] - | x :: xs -> let r = f i x in r :: loop (i+1) xs - in - loop 0 xs - -let uniq ?(cmp = Pervasives.compare) xs - let rec loop acc = function - | [] -> acc - | [x] -> x :: acc - | x :: (y :: _ as xs) when cmp x y = 0 -> - loop acc xs - | x :: (y :: _ as xs) -> - loop (x :: acc) xs - in - List.rev (loop [] xs) - -let sort_uniq ?(cmp = Pervasives.compare) xs - let xs = List.sort cmp xs in - let xs = uniq ~cmp xs in - xs - -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 explode str - let r = ref [] in - for i = 0 to String.length str - 1 do - let c = String.unsafe_get str i in - r := c :: !r; - done; - List.rev !r - -let map_chars f str - List.map f (explode str) - let name_of_argt = function | Pathname n | Device n | Mountable n | Dev_or_Path n | Mountable_or_Path n | String n | OptString n @@ -290,14 +149,20 @@ let seq_of_test = function | TestRunOrUnsupported 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 + let str = String.replace str "\\" "\\\\" in + let str = String.replace str "\r" "\\r" in + let str = String.replace str "\n" "\\n" in + let str = String.replace str "\t" "\\t" in + let str = String.replace str "\000" "\\0" in + let str = String.replace str "\"" "\\\"" in str +let html_escape text + let text = String.replace text "&" "&" in + let text = String.replace text "<" "<" in + let text = String.replace text ">" ">" in + text + (* Used to memoize the result of pod2text. *) type memo_key = int option * bool * bool * string * string (* width, trim, discard, name, longdesc *) @@ -356,7 +221,7 @@ let pod2text ?width ?(trim = true) ?(discard = true) name longdesc if i = 1 && discard then (* discard the first line of output *) loop (i+1) else ( - let line = if trim then triml line else line in + let line = if trim then String.triml line else line in lines := line :: !lines; loop (i+1) ) in @@ -376,8 +241,6 @@ let pod2text ?width ?(trim = true) ?(discard = true) name longdesc (* Compare two actions (for sorting). *) let action_compare { name = n1 } { name = n2 } = compare n1 n2 -let spaces n = String.make n ' ' - let args_of_optargs optargs List.map ( function @@ -387,9 +250,3 @@ let args_of_optargs optargs | OString n -> String n | OStringList n -> StringList n ) optargs - -let html_escape text - let text = replace_str text "&" "&" in - let text = replace_str text "<" "<" in - let text = replace_str text ">" ">" in - text diff --git a/generator/utils.mli b/generator/utils.mli index c7d3f2c..ae6f239 100644 --- a/generator/utils.mli +++ b/generator/utils.mli @@ -44,65 +44,10 @@ val rstructs_used_by : Types.action list -> (string * rstructs_used_t) list val failwithf : ('a, unit, string, 'b) format4 -> 'a (** Like [failwith] but supports printf-like arguments. *) -val unique : unit -> int -(** Returns a unique number each time called. *) - -val replace_char : string -> char -> char -> string -(** Replace character in string. *) - -val isspace : char -> bool -(** Return true if char is a whitespace character. *) - -val triml : ?test:(char -> bool) -> string -> string -(** Trim left. *) - -val trimr : ?test:(char -> bool) -> string -> string -(** Trim right. *) - -val trim : ?test:(char -> bool) -> string -> string -(** Trim left and right. *) - -val find : string -> string -> int -(** [find str sub] searches for [sub] in [str], returning the index - or -1 if not found. *) - -val replace_str : string -> string -> string -> string -(** [replace_str str s1 s2] replaces [s1] with [s2] throughout [str]. *) - -val string_split : string -> string -> string list -(** [string_split sep str] splits [str] at [sep]. *) - val files_equal : string -> string -> bool (** [files_equal filename1 filename2] returns true if the files contain the same content. *) -val (|>) : 'a -> ('a -> 'b) -> 'b -(** Added in OCaml 4.01, we can remove our definition when we - can assume this minimum version of OCaml. *) - -val filter_map : ('a -> 'b option) -> 'a list -> 'b list - -val find_map : ('a -> 'b option) -> 'a list -> 'b - -val iteri : (int -> 'a -> unit) -> 'a list -> unit - -val mapi : (int -> 'a -> 'b) -> 'a list -> 'b list - -val uniq : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list -(** Uniquify a list (the list must be sorted first). *) - -val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list -(** Sort and uniquify a list. *) - -val count_chars : char -> string -> int -(** Count number of times the character occurs in string. *) - -val explode : string -> char list -(** Explode a string into a list of characters. *) - -val map_chars : (char -> 'a) -> string -> 'a list -(** Explode string, then map function over the characters. *) - val name_of_argt : Types.argt -> string (** Extract argument name. *) @@ -115,6 +60,9 @@ val seq_of_test : Types.c_api_test -> Types.seq val c_quote : string -> string (** Perform quoting on a string so it is safe to include in a C source file. *) +val html_escape : string -> string +(** Escape a text for HTML display. *) + val pod2text : ?width:int -> ?trim:bool -> ?discard:bool -> string -> string -> string list (** [pod2text ?width ?trim ?discard name longdesc] converts the POD in [longdesc] to plain ASCII lines of text. @@ -133,11 +81,5 @@ val pod2text : ?width:int -> ?trim:bool -> ?discard:bool -> string -> string -> val action_compare : Types.action -> Types.action -> int (** Compare the names of two actions, for sorting. *) -val spaces : int -> string -(** [spaces n] creates a string of n spaces. *) - val args_of_optargs : Types.optargs -> Types.args (** Convert a list of optargs into an equivalent list of args *) - -val html_escape : string -> string -(** Escape a text for HTML display. *) diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml index 78618f5..e1d1ab8 100644 --- a/mllib/common_utils.ml +++ b/mllib/common_utils.ml @@ -16,7 +16,13 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *) +(* The parts between <stdlib>..</stdlib> are copied into the + * generator/common_utils.ml file. These parts must ONLY use + * functions from the OCaml stdlib. + *) +(*<stdlib>*) open Printf +(*</stdlib>*) open Common_gettext.Gettext open Getopt.OptionName @@ -25,6 +31,8 @@ external c_inspect_decrypt : Guestfs.t -> int64 -> unit = "guestfs_int_mllib_ins external c_set_echo_keys : unit -> unit = "guestfs_int_mllib_set_echo_keys" "noalloc" external c_set_keys_from_stdin : unit -> unit = "guestfs_int_mllib_set_keys_from_stdin" "noalloc" +(*<stdlib>*) + module Char = struct include Char @@ -37,6 +45,20 @@ module Char = struct if (c >= 'a' && c <= 'z') then unsafe_chr (code c - 32) else c + + let isspace c + c = ' ' + (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *) + + let isdigit = function + | '0'..'9' -> true + | _ -> false + + let isxdigit = function + | '0'..'9' -> true + | 'a'..'f' -> true + | 'A'..'F' -> true + | _ -> false end module String = struct @@ -53,6 +75,11 @@ module String = struct let lowercase_ascii s = map Char.lowercase_ascii s let uppercase_ascii s = map Char.uppercase_ascii s + let capitalize_ascii s + let b = Bytes.of_string s in + Bytes.unsafe_set b 0 (Char.uppercase_ascii (Bytes.unsafe_get b 0)); + Bytes.to_string b + let is_prefix str prefix let n = length prefix in length str >= n && sub str 0 n = prefix @@ -92,6 +119,17 @@ module String = struct s' ^ s2 ^ replace s'' s1 s2 ) + let replace_char s c1 c2 + let b2 = Bytes.of_string s in + let r = ref false in + for i = 0 to Bytes.length b2 - 1 do + if Bytes.unsafe_get b2 i = c1 then ( + Bytes.unsafe_set b2 i c2; + r := true + ) + done; + if not !r then s else Bytes.to_string b2 + let rec nsplit sep str let len = length str in let seplen = length sep in @@ -152,10 +190,49 @@ module String = struct make 1 c ) [1;2;3;4;5;6;7;8] ) + + let triml ?(test = Char.isspace) str + let i = ref 0 in + let n = ref (String.length str) in + while !n > 0 && test str.[!i]; do + decr n; + incr i + done; + if !i = 0 then str + else String.sub str !i !n + + let trimr ?(test = Char.isspace) str + let n = ref (String.length str) in + while !n > 0 && test str.[!n-1]; do + decr n + done; + if !n = String.length str then str + else String.sub str 0 !n + + let trim ?(test = Char.isspace) str + trimr ~test (triml ~test str) + + 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 explode str + let r = ref [] in + for i = 0 to String.length str - 1 do + let c = String.unsafe_get str i in + r := c :: !r; + done; + List.rev !r + + let map_chars f str + List.map f (explode str) + + let spaces n = String.make n ' ' end -exception Executable_not_found of string (* executable *) - let (//) = Filename.concat let ( +^ ) = Int64.add @@ -191,16 +268,6 @@ let le32_of_int i Bytes.unsafe_set b 3 (Char.unsafe_chr (Int64.to_int c3)); Bytes.to_string b -let isdigit = function - | '0'..'9' -> true - | _ -> false - -let isxdigit = function - | '0'..'9' -> true - | 'a'..'f' -> true - | 'A'..'F' -> true - | _ -> false - type wrap_break_t = WrapEOS | WrapSpace | WrapNL let rec wrap ?(chan = stdout) ?(indent = 0) str @@ -237,6 +304,8 @@ and _wrap_find_next_break i len str and output_spaces chan n = for i = 0 to n-1 do output_char chan ' ' done +let (|>) x f = f x + (* Drop elements from a list while a predicate is true. *) let rec dropwhile f = function | [] -> [] @@ -255,6 +324,13 @@ let rec filter_map f = function | Some y -> y :: filter_map f xs | None -> filter_map f xs +let rec find_map f = function + | [] -> raise Not_found + | x :: xs -> + match f x with + | Some y -> y + | None -> find_map f xs + let iteri f xs let rec loop i = function | [] -> () @@ -326,6 +402,8 @@ let pop_front xsp let append xsp xs = xsp := !xsp @ xs let prepend xs xsp = xsp := xs @ !xsp +let unique = let i = ref 0 in fun () -> incr i; !i + let may f = function | None -> () | Some x -> f x @@ -339,6 +417,8 @@ let protect ~f ~finally finally (); match r with Either ret -> ret | Or exn -> raise exn +exception Executable_not_found of string (* executable *) + let which executable let paths try String.nsplit ":" (Sys.getenv "PATH") @@ -390,6 +470,8 @@ let ansi_magenta ?(chan = stdout) () let ansi_restore ?(chan = stdout) () if colours () || istty chan then output_string chan "\x1b[0m" +(*</stdlib>*) + (* Timestamped progress messages, used for ordinary messages when not * --quiet. *) @@ -497,6 +579,8 @@ let print_version_and_exit () let generated_by sprintf (f_"generated by %s %s") prog Guestfs_config.package_version_full +(*<stdlib>*) + let read_whole_file path let buf = Buffer.create 16384 in let chan = open_in path in @@ -513,6 +597,8 @@ let read_whole_file path close_in chan; Buffer.contents buf +(*</stdlib>*) + (* Parse a size field, eg. "10G". *) let parse_size let const_re = Str.regexp "^\\([.0-9]+\\)\\([bKMG]\\)$" in @@ -627,6 +713,8 @@ let create_standard_options argspec ?anon_fun ?(key_opts = false) usage_msg else []) in Getopt.create argspec ?anon_fun usage_msg +(*<stdlib>*) + (* Compare two version strings intelligently. *) let rex_numbers = Str.regexp "^\\([0-9]+\\)\\(.*\\)$" let rex_letters = Str.regexp_case_fold "^\\([a-z]+\\)\\(.*\\)$" @@ -684,6 +772,8 @@ let stringify_args args | [] -> "" | app :: xs -> app ^ quote_args xs +(*</stdlib>*) + (* Run an external command, slurp up the output as a list of lines. *) let external_command ?(echo_cmd = true) cmd if echo_cmd then @@ -748,6 +838,8 @@ let uuidgen () if len < 10 then assert false; (* sanity check on uuidgen *) uuid +(*<stdlib>*) + (* Unlink a temporary file on exit. *) let unlink_on_exit let files = ref [] in @@ -769,6 +861,8 @@ let unlink_on_exit registered_handlers := true ) +(*</stdlib>*) + (* Remove a temporary directory on exit. *) let rmdir_on_exit let dirs = ref [] in @@ -905,6 +999,8 @@ let detect_file_type filename close_in chan; ret +(*<stdlib>*) + let is_block_device file try (Unix.stat file).Unix.st_kind = Unix.S_BLK with Unix.Unix_error _ -> false @@ -913,6 +1009,8 @@ let is_char_device file try (Unix.stat file).Unix.st_kind = Unix.S_CHR with Unix.Unix_error _ -> false +(*</stdlib>*) + let is_partition dev try if not (is_block_device dev) then false @@ -926,6 +1024,8 @@ let is_partition dev ) with Unix.Unix_error _ -> false +(*<stdlib>*) + (* Annoyingly Sys.is_directory throws an exception on failure * (RHBZ#1022431). *) @@ -995,6 +1095,8 @@ let is_regular_file path = (* NB: follows symlinks. *) try (Unix.stat path).Unix.st_kind = Unix.S_REG with Unix.Unix_error _ -> false +(*</stdlib>*) + let inspect_mount_root g ?mount_opts_fn root let mps = g#inspect_get_mountpoints root in let cmp (a,_) (b,_) diff --git a/mllib/common_utils.mli b/mllib/common_utils.mli index ad43345..7b142d4 100644 --- a/mllib/common_utils.mli +++ b/mllib/common_utils.mli @@ -16,6 +16,12 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *) +(* The parts between <stdlib>..</stdlib> are copied into the + * generator/common_utils.ml file. These parts must ONLY use + * functions from the OCaml stdlib. + *) +(*<stdlib>*) + module Char : sig type t = char val chr : int -> char @@ -26,6 +32,13 @@ module Char : sig val lowercase_ascii : char -> char val uppercase_ascii : char -> char + + val isspace : char -> bool + (** Return true if char is a whitespace character. *) + val isdigit : char -> bool + (** Return true if the character is a digit [[0-9]]. *) + val isxdigit : char -> bool + (** Return true if the character is a hex digit [[0-9a-fA-F]]. *) end (** Override the Char module from stdlib. *) @@ -53,6 +66,7 @@ module String : sig val lowercase_ascii : string -> string val uppercase_ascii : string -> string + val capitalize_ascii : string -> string val is_prefix : string -> string -> bool (** [is_prefix str prefix] returns true if [prefix] is a prefix of [str]. *) @@ -64,6 +78,8 @@ module String : sig val replace : string -> string -> string -> string (** [replace str s1 s2] replaces all instances of [s1] appearing in [str] with [s2]. *) + val replace_char : string -> char -> char -> string + (** Replace character in string. *) val nsplit : string -> string -> string list (** [nsplit sep str] splits [str] into multiple strings at each separator [sep]. *) @@ -77,13 +93,23 @@ module String : sig characters (i.e. [\] at the end of lines) into account. *) val random8 : unit -> string (** Return a string of 8 random printable characters. *) + val triml : ?test:(char -> bool) -> string -> string + (** Trim left. *) + val trimr : ?test:(char -> bool) -> string -> string + (** Trim right. *) + val trim : ?test:(char -> bool) -> string -> string + (** Trim left and right. *) + val count_chars : char -> string -> int + (** Count number of times the character occurs in string. *) + val explode : string -> char list + (** Explode a string into a list of characters. *) + val map_chars : (char -> 'a) -> string -> 'a list + (** Explode string, then map function over the characters. *) + val spaces : int -> string + (** [spaces n] creates a string of n spaces. *) end (** Override the String module from stdlib. *) -(** Exception thrown by [which] when the specified executable is not found - in [$PATH]. *) -exception Executable_not_found of string (* executable *) - val ( // ) : string -> string -> string (** Concatenate directory and filename. *) @@ -105,17 +131,16 @@ val int_of_le32 : string -> int64 val le32_of_int : int64 -> string (** Pack a 32 bit integer a 4 byte string stored little endian. *) -val isdigit : char -> bool -(** Return true if the character is a digit [[0-9]]. *) -val isxdigit : char -> bool -(** Return true if the character is a hex digit [[0-9a-fA-F]]. *) - val wrap : ?chan:out_channel -> ?indent:int -> string -> unit (** Wrap text. *) val output_spaces : out_channel -> int -> unit (** Write [n] spaces to [out_channel]. *) +val (|>) : 'a -> ('a -> 'b) -> 'b +(** Added in OCaml 4.01, we can remove our definition when we + can assume this minimum version of OCaml. *) + val dropwhile : ('a -> bool) -> 'a list -> 'a list (** [dropwhile f xs] drops leading elements from [xs] until [f] returns false. *) @@ -128,6 +153,10 @@ val takewhile : ('a -> bool) -> 'a list -> 'a list val filter_map : ('a -> 'b option) -> 'a list -> 'b list (** [filter_map f xs] applies [f] to each element of [xs]. If [f x] returns [Some y] then [y] is added to the returned list. *) +val find_map : ('a -> 'b option) -> 'a list -> 'b +(** [find_map f xs] applies [f] to each element of [xs] until + [f x] returns [Some y]. It returns [y]. If we exhaust the + list then this raises [Not_found]. *) val iteri : (int -> 'a -> 'b) -> 'a list -> unit (** [iteri f xs] calls [f i x] for each element, with [i] counting from [0]. *) val mapi : (int -> 'a -> 'b) -> 'a list -> 'b list @@ -191,6 +220,9 @@ val prepend : 'a list -> 'a list ref -> unit [prepend] is like {!push_front} above, except it prepends a list to the list reference. *) +val unique : unit -> int +(** Returns a unique number each time called. *) + val may : ('a -> unit) -> 'a option -> unit (** [may f (Some x)] runs [f x]. [may f None] does nothing. *) @@ -209,6 +241,8 @@ val protect : f:(unit -> 'a) -> finally:(unit -> unit) -> 'a case, but requires a lot more work by the caller. Perhaps we will change this in future.) *) +(*</stdlib>*) + val prog : string (** The program name (derived from {!Sys.executable_name}). *) @@ -253,9 +287,13 @@ val run_main_and_handle_errors : (unit -> unit) -> unit val generated_by : string (** The string ["generated by <prog> <version>"]. *) +(*<stdlib>*) + val read_whole_file : string -> string (** Read in the whole file as a string. *) +(*</stdlib>*) + val parse_size : string -> int64 (** Parse a size field, eg. [10G] *) @@ -275,6 +313,8 @@ val create_standard_options : Getopt.speclist -> ?anon_fun:Getopt.anon_fun -> ?k Returns a new [Getopt.t] handle. *) +(*<stdlib>*) + val compare_version : string -> string -> int (** Compare two version strings. *) @@ -285,6 +325,8 @@ val stringify_args : string list -> string (** Create a "pretty-print" representation of a program invocation (i.e. executable and its arguments). *) +(*</stdlib>*) + val external_command : ?echo_cmd:bool -> string -> string list (** Run an external command, slurp up the output as a list of lines. @@ -306,9 +348,13 @@ val shell_command : ?echo_cmd:bool -> string -> int val uuidgen : unit -> string (** Run uuidgen to return a random UUID. *) +(*<stdlib>*) + val unlink_on_exit : string -> unit (** Unlink a temporary file on exit. *) +(*</stdlib>*) + val rmdir_on_exit : string -> unit (** Remove a temporary directory on exit (using [rm -rf]). *) @@ -344,15 +390,21 @@ val debug_augeas_errors : Guestfs.guestfs -> unit val detect_file_type : string -> [`GZip | `Tar | `XZ | `Zip | `Unknown] (** Detect type of a file (for a very limited range of file types). *) +(*<stdlib>*) + val is_block_device : string -> bool val is_char_device : string -> bool val is_directory : string -> bool (** These don't throw exceptions, unlike the [Sys] functions. *) +(*</stdlib>*) + val is_partition : string -> bool (** Return true if the host device [dev] is a partition. If it's anything else, or missing, returns false. *) +(*<stdlib>*) + val absolute_path : string -> string (** Convert any path to an absolute path. *) @@ -381,6 +433,8 @@ val read_first_line_from_file : string -> string val is_regular_file : string -> bool (** Checks whether the file is a regular file. *) +(*</stdlib>*) + val inspect_mount_root : Guestfs.guestfs -> ?mount_opts_fn:(string -> string) -> string -> unit (** Mounts all the mount points of the specified root, just like [guestfish -i] does. @@ -395,6 +449,10 @@ val inspect_mount_root_ro : Guestfs.guestfs -> string -> unit val is_btrfs_subvolume : Guestfs.guestfs -> string -> bool (** Checks if a filesystem is a btrfs subvolume. *) +exception Executable_not_found of string (* executable *) +(** Exception thrown by [which] when the specified executable is not found + in [$PATH]. *) + val which : string -> string (** Return the full path of the specified executable from [$PATH]. diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml index f8337a0..558caac 100644 --- a/v2v/convert_windows.ml +++ b/v2v/convert_windows.ml @@ -113,7 +113,8 @@ let convert ~keep_serial_console (g : G.guestfs) inspect source rcaps *) let is_gpo_guid name let len = String.length name in - len > 3 && name.[0] = '{' && isxdigit name.[1] && name.[len-1] = '}' + len > 3 && name.[0] = '{' && + Char.isxdigit name.[1] && name.[len-1] = '}' in List.exists is_gpo_guid children with -- 2.10.2
Pino Toscano
2016-Dec-09 09:20 UTC
Re: [Libguestfs] [PATCH] generator: Share Common_utils code.
On Thursday, 8 December 2016 10:36:45 CET Richard W.M. Jones wrote:> For a very long time we have maintained two sets of utility functions, > in mllib/common_utils.ml and generator/utils.ml. This changes things > so that the same set of utility functions can be shared with both > directories. > > It's not possible to use common_utils.ml directly in the generator > because it provides several functions that use modules outside the > OCaml stdlib. Therefore we add some lightweight post-processing which > extracts the functions using only the stdlib: > > (*<stdlib>*) > ... > (*</stdlib>*)One idea here: instead of using a custom <stdlib> markup and sed code for it, what about using the standard C preprocessor for this? I.e. have comments like: (* #ifdef STDLIB *) ... (* #endif *) and using cpp -DSTDLIB ... to output that.> diff --git a/generator/utils.ml b/generator/utils.ml > index 3e81433..ba5e045 100644 > --- a/generator/utils.ml > +++ b/generator/utils.ml > @@ -23,6 +23,8 @@ > * makes this a bit harder than it should be. > *) > > +open Common_utils > + > open Unix > open Printf > > @@ -119,85 +121,6 @@ let rstructs_used_by functions > > let failwithf fs = ksprintf failwith fs > > -let unique = let i = ref 0 in fun () -> incr i; !iThis seems to be used only in generator, so I'd leave it here for now (reduces the changes in this patch, and it can always be moved later on when needed).> -let replace_char s c1 c2 > - let b2 = Bytes.of_string s in > - let r = ref false in > - for i = 0 to Bytes.length b2 - 1 do > - if Bytes.unsafe_get b2 i = c1 then ( > - Bytes.unsafe_set b2 i c2; > - r := true > - ) > - done; > - if not !r then s else Bytes.to_string b2Ditto.> -let isspace c > - c = ' ' > - (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)Ditto.> -let triml ?(test = isspace) str > - let i = ref 0 in > - let n = ref (String.length str) in > - while !n > 0 && test str.[!i]; do > - decr n; > - incr i > - done; > - if !i = 0 then str > - else String.sub str !i !n > - > -let trimr ?(test = isspace) str > - let n = ref (String.length str) in > - while !n > 0 && test str.[!n-1]; do > - decr n > - done; > - if !n = String.length str then str > - else String.sub str 0 !n > - > -let trim ?(test = isspace) str > - trimr ~test (triml ~test str)Ditto.> -let (|>) x f = f xDitto.> -let rec find_map f = function > - | [] -> raise Not_found > - | x :: xs -> > - match f x with > - | Some y -> y > - | None -> find_map f xsDitto. Also it does not seem to be used anywhere.> -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; > - !countDitto.> -let explode str > - let r = ref [] in > - for i = 0 to String.length str - 1 do > - let c = String.unsafe_get str i in > - r := c :: !r; > - done; > - List.rev !rDitto.> -let map_chars f str > - List.map f (explode str)Ditto.> -let spaces n = String.make n ' 'Oh there's a copy of this in mllib/getopt.ml, so could you please include that in this patch?> - > -let html_escape text > - let text = replace_str text "&" "&" in > - let text = replace_str text "<" "<" in > - let text = replace_str text ">" ">" in > - textNot a big deal, but could this be left here to reduce the diff?> diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml > index 78618f5..e1d1ab8 100644 > --- a/mllib/common_utils.ml > +++ b/mllib/common_utils.ml > @@ -16,7 +16,13 @@ > * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > *) > > +(* The parts between <stdlib>..</stdlib> are copied into the > + * generator/common_utils.ml file. These parts must ONLY use > + * functions from the OCaml stdlib. > + *) > +(*<stdlib>*) > open Printf > +(*</stdlib>*)Theoretically this could stay in both version, couldn't it? This way there are less changes between the mllib version and the generation one. Thanks, -- Pino Toscano
Richard W.M. Jones
2016-Dec-09 11:19 UTC
Re: [Libguestfs] [PATCH] generator: Share Common_utils code.
On Fri, Dec 09, 2016 at 10:20:36AM +0100, Pino Toscano wrote:> On Thursday, 8 December 2016 10:36:45 CET Richard W.M. Jones wrote: > > For a very long time we have maintained two sets of utility functions, > > in mllib/common_utils.ml and generator/utils.ml. This changes things > > so that the same set of utility functions can be shared with both > > directories. > > > > It's not possible to use common_utils.ml directly in the generator > > because it provides several functions that use modules outside the > > OCaml stdlib. Therefore we add some lightweight post-processing which > > extracts the functions using only the stdlib: > > > > (*<stdlib>*) > > ... > > (*</stdlib>*) > > One idea here: instead of using a custom <stdlib> markup and sed code > for it, what about using the standard C preprocessor for this? > I.e. have comments like: > > (* > #ifdef STDLIB > *) > ... > (* > #endif > *) > > and using cpp -DSTDLIB ... to output that.OK good idea, I'll do that instead.> > diff --git a/generator/utils.ml b/generator/utils.ml > > index 3e81433..ba5e045 100644 > > --- a/generator/utils.ml > > +++ b/generator/utils.ml > > @@ -23,6 +23,8 @@ > > * makes this a bit harder than it should be. > > *) > > > > +open Common_utils > > + > > open Unix > > open Printf > > > > @@ -119,85 +121,6 @@ let rstructs_used_by functions > > > > let failwithf fs = ksprintf failwith fs > > > > -let unique = let i = ref 0 in fun () -> incr i; !i > > This seems to be used only in generator, so I'd leave it here for now > (reduces the changes in this patch, and it can always be moved later > on when needed).[...]> Ditto.Since these were generically useful functions I felt we might as well have them in the common utils code. Maybe we'll use them in future. I don't know if this makes binaries bigger -- possibly it does by a small amount.> > -let spaces n = String.make n ' ' > > Oh there's a copy of this in mllib/getopt.ml, so could you please > include that in this patch?OK.> > diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml > > index 78618f5..e1d1ab8 100644 > > --- a/mllib/common_utils.ml > > +++ b/mllib/common_utils.ml > > @@ -16,7 +16,13 @@ > > * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > > *) > > > > +(* The parts between <stdlib>..</stdlib> are copied into the > > + * generator/common_utils.ml file. These parts must ONLY use > > + * functions from the OCaml stdlib. > > + *) > > +(*<stdlib>*) > > open Printf > > +(*</stdlib>*) > > Theoretically this could stay in both version, couldn't it? This way > there are less changes between the mllib version and the generation one.Not sure I understand. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 100 libraries supported. http://fedoraproject.org/wiki/MinGW
Richard W.M. Jones
2016-Dec-09 11:24 UTC
Re: [Libguestfs] [PATCH] generator: Share Common_utils code.
On Fri, Dec 09, 2016 at 10:20:36AM +0100, Pino Toscano wrote:> On Thursday, 8 December 2016 10:36:45 CET Richard W.M. Jones wrote: > > For a very long time we have maintained two sets of utility functions, > > in mllib/common_utils.ml and generator/utils.ml. This changes things > > so that the same set of utility functions can be shared with both > > directories. > > > > It's not possible to use common_utils.ml directly in the generator > > because it provides several functions that use modules outside the > > OCaml stdlib. Therefore we add some lightweight post-processing which > > extracts the functions using only the stdlib: > > > > (*<stdlib>*) > > ... > > (*</stdlib>*) > > One idea here: instead of using a custom <stdlib> markup and sed code > for it, what about using the standard C preprocessor for this? > I.e. have comments like: > > (* > #ifdef STDLIB > *) > ... > (* > #endif > *) > > and using cpp -DSTDLIB ... to output that.Actually I think this doesn't work because you end up with broken comments. I can't think of a good way around that at the moment. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-builder quickly builds VMs from scratch http://libguestfs.org/virt-builder.1.html
Richard W.M. Jones
2016-Dec-09 11:25 UTC
Re: [Libguestfs] [PATCH] generator: Share Common_utils code.
On Fri, Dec 09, 2016 at 10:20:36AM +0100, Pino Toscano wrote:> > -let spaces n = String.make n ' ' > > Oh there's a copy of this in mllib/getopt.ml, so could you please > include that in this patch?There's a dependency issue here which prevents getopt.ml from using functions from common_utils.ml ... Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://people.redhat.com/~rjones/virt-df/
Reasonably Related Threads
- [PATCH] generator: Add visibility to action struct
- [PATCH 1/2] c: NFC Remove redundant parentheses
- [PATCH 2/9] ocaml: Replace pattern matching { field = field } with { field }.
- [PATCH 07/27] daemon: Reimplement ‘is_dir’, ‘is_file’ and ‘is_symlink’ APIs in OCaml.
- Re: [PATCH] generator: Share Common_utils code.