mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
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:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
14
po/POTFILES
14
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
|
||||
|
||||
Reference in New Issue
Block a user