From: "Richard W.M. Jones" <rjones(a)redhat.com>
In C, a function called 'func' which has once_had_no_optargs=true will
(because of the previous commit) generate 'func_opts' and a
backwards-compatibility function called 'func'.
This commit changes some of the non-C bindings so that they also
generate 'func_opts' which is merely a wrapper that calls 'func'.
This avoids incompatibility when we rename 'mkfs_opts' etc back to
plain 'mkfs', and it also makes it easier to translate between other
language bindings and C code.
NB: Some bindings do not include aliases:
PHP: There's no way to easily alias methods in PHP < 5.3, and we
can't assume everyone has this minimum version.
GObject: Very complex to add aliases, but we should probably do this
at some point.
Haskell: No support for optargs in these bindings. Unfortunately
this means that we can no longer bind 'Guestfs.add_drive'
(since it will be changed to add optional arguments) making
the Haskell bindings even less useful than they were already.
---
generator/generator_actions.ml | 6 +++--
generator/generator_csharp.ml | 20 ++++++++++++---
generator/generator_erlang.ml | 54 +++++++++++++++++++++++++++++++++++-----
generator/generator_fish.ml | 28 +++++++++++++++------
generator/generator_java.ml | 48 ++++++++++++++++++++++++++++++++++-
generator/generator_ocaml.ml | 38 +++++++++++++++++++++-------
generator/generator_perl.ml | 36 +++++++++++++++++++++++++--
generator/generator_python.ml | 8 +++++-
generator/generator_ruby.ml | 12 +++++++--
generator/generator_types.ml | 2 ++
10 files changed, 218 insertions(+), 34 deletions(-)
diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml
index 97b0290..0073c45 100644
--- a/generator/generator_actions.ml
+++ b/generator/generator_actions.ml
@@ -32,7 +32,8 @@ let defaults = { name = ""; style = RErr, [], []; proc_nr =
None;
progress = false; camel_name = "";
cancellable = false; config_only = false;
once_had_no_optargs = false;
- c_name = ""; c_function = ""; c_optarg_prefix =
"" }
+ c_name = ""; c_function = ""; c_optarg_prefix =
"";
+ non_c_aliases = [] }
(* These test functions are used in the language binding tests. *)
@@ -9319,7 +9320,8 @@ let non_daemon_functions, daemon_functions =
{ f with
c_name = f.name ^ "_opts";
c_function = "guestfs_" ^ f.name ^ "_opts_argv";
- c_optarg_prefix = "GUESTFS_" ^ String.uppercase f.name ^
"_OPTS" }
+ c_optarg_prefix = "GUESTFS_" ^ String.uppercase f.name ^
"_OPTS";
+ non_c_aliases = [ f.name ^ "_opts" ] }
in
let non_daemon_functions = List.map make_c_function non_daemon_functions in
let daemon_functions = List.map make_c_function daemon_functions in
diff --git a/generator/generator_csharp.ml b/generator/generator_csharp.ml
index 70b9a8d..e1a31cf 100644
--- a/generator/generator_csharp.ml
+++ b/generator/generator_csharp.ml
@@ -136,7 +136,7 @@ namespace Guestfs
(* Generate C# function bindings. *)
List.iter (
fun { name = name; style = ret, args, optargs; c_function = c_function;
- shortdesc = shortdesc } ->
+ shortdesc = shortdesc; non_c_aliases = non_c_aliases } ->
let rec csharp_return_type () =
match ret with
| RErr -> "void"
@@ -204,7 +204,7 @@ namespace Guestfs
if optargs <> [] then pr ", void *";
pr ");\n"
- and generate_public_prototype () =
+ and generate_public_prototype name =
pr " public %s %s (" (csharp_return_type ()) name;
let comma = ref false in
let next () =
@@ -237,15 +237,27 @@ namespace Guestfs
*)
if optargs <> [] then pr ", NULL";
pr ");\n";
+
+ and generate_alias alias =
+ generate_public_prototype alias;
+ pr " {\n";
+ (match ret with
+ | RErr -> pr " ";
+ | _ -> pr " return "
+ );
+ pr "%s (%s);\n" name (String.concat ", " (List.map
name_of_argt args));
+ pr " }\n";
+ pr "\n";
in
pr " [DllImport (\"%s\")]\n" library;
generate_extern_prototype ();
pr "\n";
+
pr " /// <summary>\n";
pr " /// %s\n" shortdesc;
pr " /// </summary>\n";
- generate_public_prototype ();
+ generate_public_prototype name;
pr " {\n";
pr " %s r;\n" (c_return_type ());
pr " r = ";
@@ -268,6 +280,8 @@ namespace Guestfs
);
pr " }\n";
pr "\n";
+
+ List.iter generate_alias non_c_aliases
) all_functions_sorted;
pr " }
diff --git a/generator/generator_erlang.ml b/generator/generator_erlang.ml
index 083b573..3c2c04d 100644
--- a/generator/generator_erlang.ml
+++ b/generator/generator_erlang.ml
@@ -40,12 +40,16 @@ let rec generate_erlang_erl () =
(* Export the public actions. *)
List.iter (
- fun { name = name; style = _, args, optargs } ->
+ fun { name = name; style = _, args, optargs; non_c_aliases = aliases } ->
let nr_args = List.length args in
- if optargs = [] then
- pr "-export([%s/%d]).\n" name (nr_args+1)
- else
- pr "-export([%s/%d, %s/%d]).\n" name (nr_args+1) name (nr_args+2)
+ let export name =
+ if optargs = [] then
+ pr "-export([%s/%d]).\n" name (nr_args+1)
+ else
+ pr "-export([%s/%d, %s/%d]).\n" name (nr_args+1) name (nr_args+2)
+ in
+ export name;
+ List.iter export aliases
) all_functions_sorted;
pr "\n";
@@ -95,7 +99,7 @@ loop(Port) ->
* process which dispatches them to the port.
*)
List.iter (
- fun { name = name; style = _, args, optargs } ->
+ fun { name = name; style = _, args, optargs; non_c_aliases = aliases } ->
pr "%s(G" name;
List.iter (
fun arg ->
@@ -135,6 +139,44 @@ loop(Port) ->
pr ").\n"
);
+ (* Aliases. *)
+ List.iter (
+ fun alias ->
+ pr "%s(G" alias;
+ List.iter (
+ fun arg ->
+ pr ", %s" (String.capitalize (name_of_argt arg))
+ ) args;
+ if optargs <> [] then
+ pr ", Optargs";
+ pr ") ->\n";
+
+ pr " %s(G" name;
+ List.iter (
+ fun arg ->
+ pr ", %s" (String.capitalize (name_of_argt arg))
+ ) args;
+ if optargs <> [] then
+ pr ", Optargs";
+ pr ").\n";
+
+ if optargs <> [] then (
+ pr "%s(G" alias;
+ List.iter (
+ fun arg ->
+ pr ", %s" (String.capitalize (name_of_argt arg))
+ ) args;
+ pr ") ->\n";
+
+ pr " %s(G" name;
+ List.iter (
+ fun arg ->
+ pr ", %s" (String.capitalize (name_of_argt arg))
+ ) args;
+ pr ").\n"
+ )
+ ) aliases;
+
pr "\n"
) all_functions_sorted
diff --git a/generator/generator_fish.ml b/generator/generator_fish.ml
index 12e2acd..aba46e9 100644
--- a/generator/generator_fish.ml
+++ b/generator/generator_fish.ml
@@ -37,6 +37,11 @@ let doc_opttype_of = function
| OInt64 n -> "N"
| OString n -> ".."
+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
+ fish_alias @ non_c_aliases
+
(* Generate a lot of different functions for guestfish. *)
let generate_fish_cmds () =
generate_header CStyle GPLv2plus;
@@ -84,8 +89,9 @@ let generate_fish_cmds () =
(* List of command_entry structs. *)
List.iter (
- fun { name = name; fish_alias = aliases; shortdesc = shortdesc;
- longdesc = longdesc } ->
+ fun ({ name = name; shortdesc = shortdesc; longdesc = longdesc } as f) ->
+ let aliases = get_aliases f in
+
let name2 = replace_char name '_' '-' in
let describe_alias =
if aliases <> [] then
@@ -109,8 +115,10 @@ let generate_fish_cmds () =
) fish_commands;
List.iter (
- fun ({ name = name; style = _, args, optargs; fish_alias = aliases;
+ fun ({ name = name; style = _, args, optargs;
shortdesc = shortdesc; longdesc = longdesc } as f) ->
+ let aliases = get_aliases f in
+
let name2 = replace_char name '_' '-' in
let longdesc = replace_str longdesc "C<guestfs_" "C<" in
@@ -694,7 +702,8 @@ struct command_table;
";
List.iter (
- fun { name = name; fish_alias = aliases } ->
+ fun ({ name = name } as f) ->
+ let aliases = get_aliases f in
let name2 = replace_char name '_' '-' in
(* The basic command. *)
@@ -742,7 +751,8 @@ static const char *const commands[] = {
*)
let commands =
List.map (
- fun { name = name; fish_alias = aliases } ->
+ fun ({ name = name } as f) ->
+ let aliases = get_aliases f in
let name2 = replace_char name '_' '-' in
name2 :: aliases
) (all_functions @ fish_commands) in
@@ -813,8 +823,9 @@ and generate_fish_actions_pod () =
let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
List.iter (
- fun ({ name = name; style = _, args, optargs; fish_alias = aliases;
- longdesc = longdesc } as f) ->
+ fun ({ name = name; style = _, args, optargs; longdesc = longdesc } as f) ->
+ let aliases = get_aliases f in
+
let longdesc =
Str.global_substitute rex (
fun s ->
@@ -876,7 +887,8 @@ Guestfish will prompt for these separately.\n\n";
(* Generate documentation for guestfish-only commands. *)
and generate_fish_commands_pod () =
List.iter (
- fun { name = name; fish_alias = aliases; longdesc = longdesc } ->
+ fun ({ name = name; longdesc = longdesc } as f) ->
+ let aliases = get_aliases f in
let name = replace_char name '_' '-' in
List.iter (
diff --git a/generator/generator_java.ml b/generator/generator_java.ml
index 62a1775..d239e1f 100644
--- a/generator/generator_java.ml
+++ b/generator/generator_java.ml
@@ -95,7 +95,7 @@ public class GuestFS {
List.iter (
fun ({ name = name; style = (ret, args, optargs as style);
in_docs = in_docs; shortdesc = shortdesc;
- longdesc = longdesc } as f) ->
+ longdesc = longdesc; non_c_aliases = non_c_aliases } as f) ->
if in_docs then (
let doc = replace_str longdesc "C<guestfs_" "C<g." in
let doc =
@@ -200,6 +200,52 @@ public class GuestFS {
pr "\n"
);
+ (* Aliases. *)
+ List.iter (
+ fun alias ->
+ pr " ";
+ generate_java_prototype ~public:true ~semicolon:false alias style;
+ pr "\n";
+ pr " {\n";
+ (match ret with
+ | RErr -> pr " "
+ | _ -> pr " return "
+ );
+ pr "%s (" name;
+ let needs_comma = ref false in
+ List.iter (
+ fun arg ->
+ if !needs_comma then pr ", ";
+ needs_comma := true;
+ pr "%s" (name_of_argt arg)
+ ) args;
+ if optargs <> [] then (
+ if !needs_comma then pr ", ";
+ needs_comma := true;
+ pr "optargs"
+ );
+ pr ");\n";
+ pr " }\n";
+ pr "\n";
+
+ if optargs <> [] then (
+ pr " ";
+ generate_java_prototype ~public:true ~semicolon:false
+ alias (ret, args, []);
+ pr "\n";
+ pr " {\n";
+ (match ret with
+ | RErr -> pr " "
+ | _ -> pr " return "
+ );
+ pr "%s (" name;
+ List.iter (fun arg -> pr "%s, " (name_of_argt arg)) args;
+ pr "null);\n";
+ pr " }\n";
+ pr "\n"
+ )
+ ) non_c_aliases;
+
(* Prototype for the native method. *)
pr " ";
generate_java_prototype ~privat:true ~native:true name style;
diff --git a/generator/generator_ocaml.ml b/generator/generator_ocaml.ml
index f54ed2c..392f9cb 100644
--- a/generator/generator_ocaml.ml
+++ b/generator/generator_ocaml.ml
@@ -125,6 +125,7 @@ val user_cancel : t -> unit
(* The actions. *)
List.iter (
fun { name = name; style = style; deprecated_by = deprecated_by;
+ non_c_aliases = non_c_aliases;
in_docs = in_docs; shortdesc = shortdesc } ->
generate_ocaml_prototype name style;
@@ -137,7 +138,14 @@ val user_cancel : t -> unit
);
pr " *)\n";
);
- pr "\n"
+ pr "\n";
+
+ (* Aliases. *)
+ List.iter (
+ fun alias ->
+ generate_ocaml_prototype alias style;
+ pr "\n";
+ ) non_c_aliases;
) all_functions_sorted;
pr "\
@@ -173,15 +181,22 @@ class guestfs : unit -> object
";
List.iter (
- function
- | { name = name; style = ((_, [], _) as style) } ->
+ fun { name = name; style = style; non_c_aliases = non_c_aliases } ->
+ (match style with
+ | _, [], _ ->
pr " method %s : " name;
generate_ocaml_function_type ~extra_unit:true style;
pr "\n"
- | { name = name; style = style } ->
+ | _, (_::_), _ ->
pr " method %s : " name;
generate_ocaml_function_type style;
pr "\n"
+ );
+ List.iter (fun alias ->
+ pr " method %s : " alias;
+ generate_ocaml_function_type style;
+ pr "\n"
+ ) non_c_aliases
) all_functions_sorted;
pr "end\n"
@@ -243,15 +258,16 @@ let () =
(* The actions. *)
List.iter (
- fun { name = name; style = style } ->
+ fun { name = name; style = style; non_c_aliases = non_c_aliases } ->
generate_ocaml_prototype ~is_external:true name style;
+ List.iter (fun alias -> pr "let %s = %s\n" alias name) non_c_aliases
) all_functions_sorted;
(* OO API. *)
pr "
class guestfs () =
let g = create () in
- object
+ object (self)
method close () = close g
method set_event_callback = set_event_callback g
method delete_event_callback = delete_event_callback g
@@ -261,15 +277,19 @@ class guestfs () =
";
List.iter (
- function
- | { name = name; style = _, [], optargs } ->
+ fun { name = name; style = style; non_c_aliases = non_c_aliases } ->
+ (match style with
+ | _, [], optargs ->
(* No required params? Add explicit unit. *)
let optargs =
String.concat ""
(List.map (fun arg -> " ?" ^ name_of_optargt arg) optargs) in
pr " method %s%s () = %s g%s\n" name optargs name optargs
- | { name = name } ->
+ | _, (_::_), _ ->
pr " method %s = %s g\n" name name
+ );
+ List.iter
+ (fun alias -> pr " method %s = self#%s\n" alias name)
non_c_aliases
) all_functions_sorted;
pr " end\n"
diff --git a/generator/generator_perl.ml b/generator/generator_perl.ml
index d5cf814..b363bfc 100644
--- a/generator/generator_perl.ml
+++ b/generator/generator_perl.ml
@@ -797,7 +797,7 @@ handlers and threads.
function
| { in_docs = false } -> ()
| ({ name = name; style = style; in_docs = true;
- longdesc = longdesc } as f) ->
+ longdesc = longdesc; non_c_aliases = non_c_aliases } as f) ->
let longdesc = replace_str longdesc "C<guestfs_"
"C<$h-E<gt>" in
pr "=item ";
generate_perl_prototype name style;
@@ -805,9 +805,28 @@ handlers and threads.
pr "%s\n\n" longdesc;
if f.protocol_limit_warning then
pr "%s\n\n" protocol_limit_warning;
- match deprecation_notice f with
+ (match deprecation_notice f with
| None -> ()
| Some txt -> pr "%s\n\n" txt
+ );
+
+ (* Aliases. *)
+ List.iter (
+ fun alias ->
+ pr "=item ";
+ generate_perl_prototype alias style;
+ pr "\n";
+ pr "\n";
+ pr "This is an alias of L</%s>.\n" name;
+ pr "\n";
+ pr "=cut\n\n";
+ pr "sub %s {\n" alias;
+ pr " &%s (@_)\n" name;
+ pr "}\n";
+ pr "\n";
+ pr "=pod\n";
+ pr "\n";
+ ) non_c_aliases
) all_functions_sorted;
pr "=cut\n\n";
@@ -873,6 +892,19 @@ handlers and threads.
) all_functions_sorted;
pr ");\n\n";
+ pr "# Add aliases to the introspection hash.\n";
+ let i = ref 0 in
+ List.iter (
+ fun { name = name; non_c_aliases = non_c_aliases } ->
+ List.iter (
+ fun alias ->
+ pr "my %%ielem%d = %%{$guestfs_introspection{%s}};\n" !i name;
+ pr "$guestfs_introspection{%s} = \\%%ielem%d;\n" alias !i;
+ incr i
+ ) non_c_aliases
+ ) all_functions_sorted;
+ pr "\n";
+
(* End of file. *)
pr "\
1;
diff --git a/generator/generator_python.ml b/generator/generator_python.ml
index 548094c..dda0414 100644
--- a/generator/generator_python.ml
+++ b/generator/generator_python.ml
@@ -695,7 +695,7 @@ class GuestFS:
List.iter (
fun ({ name = name; style = ret, args, optargs; in_docs = in_docs;
- longdesc = longdesc } as f) ->
+ longdesc = longdesc; non_c_aliases = non_c_aliases } as f) ->
pr " def %s (self" name;
List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
List.iter (
@@ -750,4 +750,10 @@ class GuestFS:
List.iter (fun arg -> pr ", %s" (name_of_argt arg))
(args @ args_of_optargs optargs);
pr ")\n\n";
+
+ (* Aliases. *)
+ List.iter (
+ fun alias ->
+ pr " %s = %s\n\n" alias name
+ ) non_c_aliases
) all_functions
diff --git a/generator/generator_ruby.ml b/generator/generator_ruby.ml
index f82d90c..7ab2177 100644
--- a/generator/generator_ruby.ml
+++ b/generator/generator_ruby.ml
@@ -633,10 +633,18 @@ void Init__guestfs ()
(* Methods. *)
List.iter (
- fun { name = name; style = _, args, optargs } ->
+ fun { name = name; style = _, args, optargs;
+ non_c_aliases = non_c_aliases } ->
let nr_args = List.length args + if optargs <> [] then 1 else 0 in
pr " rb_define_method (c_guestfs, \"%s\",\n" name;
- pr " ruby_guestfs_%s, %d);\n" name nr_args
+ pr " ruby_guestfs_%s, %d);\n" name nr_args;
+
+ (* Aliases. *)
+ List.iter (
+ fun alias ->
+ pr " rb_define_method (c_guestfs, \"%s\",\n" alias;
+ pr " ruby_guestfs_%s, %d);\n" name nr_args
+ ) non_c_aliases
) all_functions;
pr "}\n"
diff --git a/generator/generator_types.ml b/generator/generator_types.ml
index ce7aea3..aeb751c 100644
--- a/generator/generator_types.ml
+++ b/generator/generator_types.ml
@@ -419,6 +419,8 @@ type action = {
c_function : string; (* full name of C API function called by
non-C bindings *)
c_optarg_prefix : string; (* prefix for optarg names/bitmask names *)
+ non_c_aliases : string list; (* back-compat aliases that have to be
+ generated for this function *)
}
(* Field types for structures. *)
--
1.7.10.4