[Libguestfs] [PATCH 4/4] fish: Split up the very large fish/cmds.c file.

Richard W.M. Jones rjones at redhat.com
Fri Sep 2 14:21:29 UTC 2016


Make parallel compiles faster in this directory (about 8s down to 3s).
---
 .gitignore         |   3 +
 fish/Makefile.am   |  17 ++-
 generator/fish.ml  | 348 ++++++++++++++++++++++++++++++-----------------------
 generator/fish.mli |   3 +
 generator/main.ml  |   3 +
 5 files changed, 220 insertions(+), 154 deletions(-)

diff --git a/.gitignore b/.gitignore
index fc0d065..8312d99 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/fish/Makefile.am b/fish/Makefile.am
index a6de568..e1bc210 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 2acd484..b16326b 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 <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";
diff --git a/generator/fish.mli b/generator/fish.mli
index bb4376a..ed52d90 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 edf106a..52b77b4 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;
-- 
2.9.3




More information about the Libguestfs mailing list