fish: Split up the very large fish/cmds.c file.

Make parallel compiles faster in this directory (about 8s down to 3s).
This commit is contained in:
Richard W.M. Jones
2016-09-02 15:05:44 +01:00
parent 4730f4a918
commit a749b5d93a
7 changed files with 248 additions and 154 deletions

3
.gitignore vendored
View File

@@ -204,6 +204,7 @@ Makefile.in
/fish/cmds-gperf.c
/fish/cmds-gperf.gperf
/fish/completion.c
/fish/entries-?.c
/fish/event-names.c
/fish/fish-cmds.h
/fish/guestfish
@@ -216,6 +217,8 @@ Makefile.in
/fish/prepopts.h
/fish/rc_protocol.c
/fish/rc_protocol.h
/fish/run-?.c
/fish/run.h
/fish/stamp-guestfish.pod
/fish/stamp-libguestfs-tools.conf.pod
/fish/stamp-virt-copy-in.pod

View File

@@ -140,6 +140,13 @@ fish/display.c
fish/domain.c
fish/echo.c
fish/edit.c
fish/entries-0.c
fish/entries-1.c
fish/entries-2.c
fish/entries-3.c
fish/entries-4.c
fish/entries-5.c
fish/entries-6.c
fish/event-names.c
fish/events.c
fish/file-edit.c
@@ -163,6 +170,13 @@ fish/prepopts.c
fish/progress.c
fish/rc.c
fish/reopen.c
fish/run-0.c
fish/run-1.c
fish/run-2.c
fish/run-3.c
fish/run-4.c
fish/run-5.c
fish/run-6.c
fish/setenv.c
fish/supported.c
fish/tilde.c

View File

@@ -23,13 +23,28 @@ generator_built = \
cmds.c \
cmds-gperf.gperf \
completion.c \
entries-0.c \
entries-1.c \
entries-2.c \
entries-3.c \
entries-4.c \
entries-5.c \
entries-6.c \
event-names.c \
fish-cmds.h \
guestfish-actions.pod \
guestfish-commands.pod \
guestfish-prepopts.pod \
prepopts.h \
prepopts.c
prepopts.c \
run-0.c \
run-1.c \
run-2.c \
run-3.c \
run-4.c \
run-5.c \
run-6.c \
run.h
BUILT_SOURCES = \
$(generator_built) \

View File

@@ -76,11 +76,10 @@ let c_quoted_indented ~indent str =
let str = replace_str str "\\n" ("\\n\"\n" ^ indent ^ "\"") in
str
(* Generate a lot of different functions for guestfish. *)
let generate_fish_cmds () =
(* Generate run_* functions and header for libguestfs API functions. *)
let generate_fish_run_cmds actions () =
generate_header CStyle GPLv2plus;
pr "#include <config.h>\n";
pr "\n";
pr "/* It is safe to call deprecated functions from this file. */\n";
@@ -93,7 +92,6 @@ let generate_fish_cmds () =
pr "#include <libintl.h>\n";
pr "#include <errno.h>\n";
pr "\n";
pr "#include \"c-ctype.h\"\n";
pr "#include \"full-write.h\"\n";
pr "#include \"xstrtol.h\"\n";
pr "\n";
@@ -102,157 +100,16 @@ let generate_fish_cmds () =
pr "#include \"structs-print.h\"\n";
pr "\n";
pr "#include \"fish.h\"\n";
pr "#include \"fish-cmds.h\"\n";
pr "#include \"options.h\"\n";
pr "#include \"cmds-gperf.h\"\n";
pr "#include \"fish-cmds.h\"\n";
pr "#include \"run.h\"\n";
pr "\n";
pr "/* Valid suffixes allowed for numbers. See Gnulib xstrtol function. */\n";
pr "static const char xstrtol_suffixes[] = \"0kKMGTPEZY\";\n";
pr "\n";
pr "/* Return these errors from run_* functions. */\n";
pr "#define RUN_ERROR -1\n";
pr "#define RUN_WRONG_ARGS -2\n";
pr "\n";
List.iter (
fun { name = name } ->
pr "static int run_%s (const char *cmd, size_t argc, char *argv[]);\n"
name
) (actions |> fish_functions |> sort);
pr "\n";
(* List of command_entry structs. *)
List.iter (
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
sprintf "\n\nYou can use %s as an alias for this command."
(String.concat " or " (List.map (fun s -> "'" ^ s ^ "'") aliases))
else "" in
let pod =
sprintf "%s - %s\n\n=head1 DESCRIPTION\n\n%s\n\n%s"
name2 shortdesc longdesc describe_alias in
let text =
String.concat "\n" (pod2text ~trim:false ~discard:false "NAME" pod)
^ "\n" in
pr "struct command_entry %s_cmd_entry = {\n" name;
pr " .name = \"%s\",\n" name2;
pr " .help = \"%s\",\n" (c_quoted_indented ~indent:" " text);
pr " .synopsis = NULL,\n";
pr " .run = run_%s\n" name;
pr "};\n";
pr "\n";
) fish_commands;
List.iter (
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
let synopsis =
match args with
| [] -> name2
| args ->
let args = List.filter (function Key _ -> false | _ -> true) args in
sprintf "%s%s%s"
name2
(String.concat ""
(List.map (fun arg -> " " ^ name_of_argt arg) args))
(String.concat ""
(List.map (fun arg ->
sprintf " [%s:%s]" (name_of_optargt arg) (doc_opttype_of arg)
) optargs)) in
let warnings =
if List.exists (function Key _ -> true | _ -> false) args then
"\n\nThis command has one or more key or passphrase parameters.
Guestfish will prompt for these separately."
else "" in
let warnings =
warnings ^
if f.protocol_limit_warning then
"\n\n" ^ protocol_limit_warning
else "" in
let warnings =
warnings ^
match deprecation_notice ~replace_underscores:true f with
| None -> ""
| Some txt -> "\n\n" ^ txt in
let describe_alias =
if aliases <> [] then
sprintf "\n\nYou can use %s as an alias for this command."
(String.concat " or " (List.map (fun s -> "'" ^ s ^ "'") aliases))
else "" in
let pod =
sprintf "%s - %s\n\n=head1 SYNOPSIS\n\n %s\n\n=head1 DESCRIPTION\n\n%s%s%s"
name2 shortdesc synopsis longdesc warnings describe_alias in
let text =
String.concat "\n" (pod2text ~trim:false ~discard:false "NAME" pod)
^ "\n" in
pr "struct command_entry %s_cmd_entry = {\n" name;
pr " .name = \"%s\",\n" name2;
pr " .help = \"%s\",\n" (c_quoted_indented ~indent:" " text);
pr " .synopsis = \"%s\",\n" (c_quote synopsis);
pr " .run = run_%s\n" name;
pr "};\n";
pr "\n";
) (actions |> fish_functions |> sort);
(* list_commands function, which implements guestfish -h *)
pr "void\n";
pr "list_commands (void)\n";
pr "{\n";
pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
pr " list_builtin_commands ();\n";
List.iter (
fun (name, f) ->
let name = 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
pr " printf (\"%%-20s \", \"%s\");\n" name;
pr " printf (_(\"alias for '%%s'\"), \"%s\");\n" f;
pr " putchar ('\\n');\n"
) all_functions_commands_and_aliases_sorted;
pr " printf (\" %%s\\n\",";
pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
pr "}\n";
pr "\n";
(* display_command function, which implements guestfish -h cmd *)
pr "int\n";
pr "display_command (const char *cmd)\n";
pr "{\n";
pr " const struct command_table *ct;\n";
pr "\n";
pr " ct = lookup_fish_command (cmd, strlen (cmd));\n";
pr " if (ct) {\n";
pr " fputs (ct->entry->help, stdout);\n";
pr " return 0;\n";
pr " }\n";
pr " else\n";
pr " return display_builtin_command (cmd);\n";
pr "}\n";
pr "\n";
let emit_print_list_function typ =
pr "\n";
pr "static void\n";
pr "print_%s_list (struct guestfs_%s_list *%ss)\n"
typ typ typ;
@@ -266,7 +123,6 @@ Guestfish will prompt for these separately."
pr " printf (\"}\\n\");\n";
pr " }\n";
pr "}\n";
pr "\n";
in
(* Emit a print_TYPE_list function definition only if that function is used. *)
@@ -282,22 +138,22 @@ Guestfish will prompt for these separately."
List.iter (
function
| typ, (RStructOnly | RStructAndList) ->
pr "\n";
pr "static void\n";
pr "print_%s (struct guestfs_%s *%s)\n" typ typ typ;
pr "{\n";
pr " guestfs_int_print_%s_indent (%s, stdout, \"\\n\", \"\");\n"
typ typ;
pr "}\n";
pr "\n";
| typ, _ -> () (* empty *)
) (rstructs_used_by (actions |> fish_functions));
(* run_<action> actions *)
List.iter (
fun { name = name; style = (ret, args, optargs as style);
fish_output = fish_output; c_function = c_function;
c_optarg_prefix = c_optarg_prefix } ->
pr "static int\n";
pr "\n";
pr "int\n";
pr "run_%s (const char *cmd, size_t argc, char *argv[])\n" name;
pr "{\n";
pr " int ret = RUN_ERROR;\n";
@@ -642,9 +498,195 @@ Guestfish will prompt for these separately."
pr " out_noargs:\n";
pr " return ret;\n";
pr "}\n";
pr "\n"
) (actions |> fish_functions |> sort)
let generate_fish_run_header () =
generate_header CStyle GPLv2plus;
pr "#ifndef FISH_RUN_H\n";
pr "#define FISH_RUN_H\n";
pr "\n";
pr "/* Return these errors from run_* functions. */\n";
pr "#define RUN_ERROR -1\n";
pr "#define RUN_WRONG_ARGS -2\n";
pr "\n";
List.iter (
fun { name = name } ->
pr "extern int run_%s (const char *cmd, size_t argc, char *argv[]);\n"
name
) (actions |> fish_functions |> sort);
pr "\n";
pr "#endif /* FISH_RUN_H */\n"
let generate_fish_cmd_entries actions () =
generate_header CStyle GPLv2plus;
pr "#include <config.h>\n";
pr "\n";
pr "#include <stdio.h>\n";
pr "#include <stdlib.h>\n";
pr "\n";
pr "#include \"cmds-gperf.h\"\n";
pr "#include \"run.h\"\n";
pr "\n";
List.iter (
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
let synopsis =
match args with
| [] -> name2
| args ->
let args = List.filter (function Key _ -> false | _ -> true) args in
sprintf "%s%s%s"
name2
(String.concat ""
(List.map (fun arg -> " " ^ name_of_argt arg) args))
(String.concat ""
(List.map (fun arg ->
sprintf " [%s:%s]" (name_of_optargt arg) (doc_opttype_of arg)
) optargs)) in
let warnings =
if List.exists (function Key _ -> true | _ -> false) args then
"\n\nThis command has one or more key or passphrase parameters.
Guestfish will prompt for these separately."
else "" in
let warnings =
warnings ^
if f.protocol_limit_warning then
"\n\n" ^ protocol_limit_warning
else "" in
let warnings =
warnings ^
match deprecation_notice ~replace_underscores:true f with
| None -> ""
| Some txt -> "\n\n" ^ txt in
let describe_alias =
if aliases <> [] then
sprintf "\n\nYou can use %s as an alias for this command."
(String.concat " or " (List.map (fun s -> "'" ^ s ^ "'") aliases))
else "" in
let pod =
sprintf "%s - %s\n\n=head1 SYNOPSIS\n\n %s\n\n=head1 DESCRIPTION\n\n%s%s%s"
name2 shortdesc synopsis longdesc warnings describe_alias in
let text =
String.concat "\n" (pod2text ~trim:false ~discard:false "NAME" pod)
^ "\n" in
pr "struct command_entry %s_cmd_entry = {\n" name;
pr " .name = \"%s\",\n" name2;
pr " .help = \"%s\",\n" (c_quoted_indented ~indent:" " text);
pr " .synopsis = \"%s\",\n" (c_quote synopsis);
pr " .run = run_%s\n" name;
pr "};\n";
pr "\n";
) (actions |> fish_functions |> sort)
(* Generate a lot of different functions for guestfish. *)
let generate_fish_cmds () =
generate_header CStyle GPLv2plus;
pr "#include <config.h>\n";
pr "\n";
pr "#include <stdio.h>\n";
pr "#include <stdlib.h>\n";
pr "#include <string.h>\n";
pr "#include <inttypes.h>\n";
pr "#include <libintl.h>\n";
pr "#include <errno.h>\n";
pr "\n";
pr "#include \"guestfs.h\"\n";
pr "#include \"guestfs-internal-frontend.h\"\n";
pr "#include \"structs-print.h\"\n";
pr "\n";
pr "#include \"fish.h\"\n";
pr "#include \"fish-cmds.h\"\n";
pr "#include \"options.h\"\n";
pr "#include \"cmds-gperf.h\"\n";
pr "#include \"run.h\"\n";
pr "\n";
(* List of command_entry structs for pure guestfish commands. *)
List.iter (
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
sprintf "\n\nYou can use %s as an alias for this command."
(String.concat " or " (List.map (fun s -> "'" ^ s ^ "'") aliases))
else "" in
let pod =
sprintf "%s - %s\n\n=head1 DESCRIPTION\n\n%s\n\n%s"
name2 shortdesc longdesc describe_alias in
let text =
String.concat "\n" (pod2text ~trim:false ~discard:false "NAME" pod)
^ "\n" in
pr "struct command_entry %s_cmd_entry = {\n" name;
pr " .name = \"%s\",\n" name2;
pr " .help = \"%s\",\n" (c_quoted_indented ~indent:" " text);
pr " .synopsis = NULL,\n";
pr " .run = run_%s\n" name;
pr "};\n";
pr "\n";
) fish_commands;
(* list_commands function, which implements guestfish -h *)
pr "void\n";
pr "list_commands (void)\n";
pr "{\n";
pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
pr " list_builtin_commands ();\n";
List.iter (
fun (name, f) ->
let name = 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
pr " printf (\"%%-20s \", \"%s\");\n" name;
pr " printf (_(\"alias for '%%s'\"), \"%s\");\n" f;
pr " putchar ('\\n');\n"
) all_functions_commands_and_aliases_sorted;
pr " printf (\" %%s\\n\",";
pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
pr "}\n";
pr "\n";
(* display_command function, which implements guestfish -h cmd *)
pr "int\n";
pr "display_command (const char *cmd)\n";
pr "{\n";
pr " const struct command_table *ct;\n";
pr "\n";
pr " ct = lookup_fish_command (cmd, strlen (cmd));\n";
pr " if (ct) {\n";
pr " fputs (ct->entry->help, stdout);\n";
pr " return 0;\n";
pr " }\n";
pr " else\n";
pr " return display_builtin_command (cmd);\n";
pr "}\n";
pr "\n";
(* run_action function *)
pr "int\n";
pr "run_action (const char *cmd, size_t argc, char *argv[])\n";

View File

@@ -17,6 +17,9 @@
*)
val generate_fish_actions_pod : unit -> unit
val generate_fish_run_cmds : Types.action list -> unit -> unit
val generate_fish_run_header : unit -> unit
val generate_fish_cmd_entries : Types.action list -> unit -> unit
val generate_fish_cmds : unit -> unit
val generate_fish_cmds_gperf : unit -> unit
val generate_fish_cmds_h : unit -> unit

View File

@@ -126,6 +126,9 @@ Run it from the top source directory using the command
output_to "tests/c-api/tests.c" generate_c_api_tests;
output_to "fish/cmds-gperf.gperf" generate_fish_cmds_gperf;
output_to "fish/cmds.c" generate_fish_cmds;
output_to_subset "fish/entries-%d.c" generate_fish_cmd_entries;
output_to_subset "fish/run-%d.c" generate_fish_run_cmds;
output_to "fish/run.h" generate_fish_run_header;
output_to "fish/completion.c" generate_fish_completion;
output_to "fish/event-names.c" generate_fish_event_names;
output_to "fish/fish-cmds.h" generate_fish_cmds_h;

View File

@@ -146,6 +146,13 @@ fish/display.c
fish/domain.c
fish/echo.c
fish/edit.c
fish/entries-0.c
fish/entries-1.c
fish/entries-2.c
fish/entries-3.c
fish/entries-4.c
fish/entries-5.c
fish/entries-6.c
fish/event-names.c
fish/events.c
fish/file-edit.c
@@ -169,6 +176,13 @@ fish/prepopts.c
fish/progress.c
fish/rc.c
fish/reopen.c
fish/run-0.c
fish/run-1.c
fish/run-2.c
fish/run-3.c
fish/run-4.c
fish/run-5.c
fish/run-6.c
fish/setenv.c
fish/supported.c
fish/tilde.c