From a749b5d93aa7f27793a5c939c985df82df406492 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 2 Sep 2016 15:05:44 +0100 Subject: [PATCH] fish: Split up the very large fish/cmds.c file. Make parallel compiles faster in this directory (about 8s down to 3s). --- .gitignore | 3 + docs/C_SOURCE_FILES | 14 ++ fish/Makefile.am | 17 ++- generator/fish.ml | 348 +++++++++++++++++++++++++------------------- generator/fish.mli | 3 + generator/main.ml | 3 + po/POTFILES | 14 ++ 7 files changed, 248 insertions(+), 154 deletions(-) diff --git a/.gitignore b/.gitignore index fc0d06566..8312d9969 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES index 97023f017..a94b009f6 100644 --- a/docs/C_SOURCE_FILES +++ b/docs/C_SOURCE_FILES @@ -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 diff --git a/fish/Makefile.am b/fish/Makefile.am index a6de5686d..e1bc210fe 100644 --- a/fish/Makefile.am +++ b/fish/Makefile.am @@ -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) \ diff --git a/generator/fish.ml b/generator/fish.ml index 2acd48430..b16326b14 100644 --- a/generator/fish.ml +++ b/generator/fish.ml @@ -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 \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 \n"; pr "#include \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 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 / help 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_ 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 \n"; + pr "\n"; + pr "#include \n"; + pr "#include \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 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 \n"; + pr "\n"; + pr "#include \n"; + pr "#include \n"; + pr "#include \n"; + pr "#include \n"; + pr "#include \n"; + pr "#include \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 / help 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"; diff --git a/generator/fish.mli b/generator/fish.mli index bb4376aaa..ed52d9012 100644 --- a/generator/fish.mli +++ b/generator/fish.mli @@ -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 diff --git a/generator/main.ml b/generator/main.ml index edf106a07..52b77b4aa 100644 --- a/generator/main.ml +++ b/generator/main.ml @@ -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; diff --git a/po/POTFILES b/po/POTFILES index 33e04b076..70213eb7a 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -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