2 * Copyright (C) 2009-2010 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 (* Please read generator/README first. *)
26 open Generator_docstrings
27 open Generator_optgroups
28 open Generator_actions
29 open Generator_structs
30 open Generator_prepopts
34 let doc_opttype_of = function
35 | OBool n -> "true|false"
40 (* Generate a lot of different functions for guestfish. *)
41 let generate_fish_cmds () =
42 generate_header CStyle GPLv2plus;
46 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
48 let all_functions_sorted =
50 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
51 ) all_functions_sorted in
53 let all_functions_and_fish_commands_sorted =
54 List.sort action_compare (all_functions_sorted @ fish_commands) in
56 pr "#include <config.h>\n";
58 pr "/* It is safe to call deprecated functions from this file. */\n";
59 pr "#undef GUESTFS_WARN_DEPRECATED\n";
61 pr "#include <stdio.h>\n";
62 pr "#include <stdlib.h>\n";
63 pr "#include <string.h>\n";
64 pr "#include <inttypes.h>\n";
66 pr "#include \"c-ctype.h\"\n";
67 pr "#include \"full-write.h\"\n";
68 pr "#include \"xstrtol.h\"\n";
70 pr "#include <guestfs.h>\n";
71 pr "#include \"fish.h\"\n";
72 pr "#include \"fish-cmds.h\"\n";
73 pr "#include \"options.h\"\n";
74 pr "#include \"cmds_gperf.h\"\n";
76 pr "/* Valid suffixes allowed for numbers. See Gnulib xstrtol function. */\n";
77 pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
81 fun (name, _, _, _, _, _, _) ->
82 pr "static int run_%s (const char *cmd, size_t argc, char *argv[]);\n"
88 (* List of command_entry structs. *)
90 fun (name, _, _, flags, _, shortdesc, longdesc) ->
91 let name2 = replace_char name '_' '-' in
93 filter_map (function FishAlias n -> Some n | _ -> None) flags in
96 sprintf "\n\nYou can use %s as an alias for this command."
97 (String.concat " or " (List.map (fun s -> "'" ^ s ^ "'") aliases))
101 sprintf "%s - %s\n\n=head1 DESCRIPTION\n\n%s\n\n%s"
102 name2 shortdesc longdesc describe_alias in
104 String.concat "\n" (pod2text ~trim:false ~discard:false "NAME" pod)
107 pr "struct command_entry %s_cmd_entry = {\n" name;
108 pr " .name = \"%s\",\n" name2;
109 pr " .help = \"%s\",\n" (c_quote text);
110 pr " .run = run_%s\n" name;
116 fun (name, (_, args, optargs), _, flags, _, shortdesc, longdesc) ->
117 let name2 = replace_char name '_' '-' in
119 filter_map (function FishAlias n -> Some n | _ -> None) flags in
121 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
126 let args = List.filter (function Key _ -> false | _ -> true) args in
130 (List.map (fun arg -> " " ^ name_of_argt arg) args))
132 (List.map (fun arg ->
133 sprintf " [%s:%s]" (name_of_optargt arg) (doc_opttype_of arg)
137 if List.exists (function Key _ -> true | _ -> false) args then
138 "\n\nThis command has one or more key or passphrase parameters.
139 Guestfish will prompt for these separately."
144 if List.mem ProtocolLimitWarning flags then
145 ("\n\n" ^ protocol_limit_warning)
150 match deprecation_notice flags with
152 | Some txt -> "\n\n" ^ txt in
155 if aliases <> [] then
156 sprintf "\n\nYou can use %s as an alias for this command."
157 (String.concat " or " (List.map (fun s -> "'" ^ s ^ "'") aliases))
161 sprintf "%s - %s\n\n=head1 SYNOPSIS\n\n %s\n\n=head1 DESCRIPTION\n\n%s%s%s"
162 name2 shortdesc synopsis longdesc warnings describe_alias in
164 String.concat "\n" (pod2text ~trim:false ~discard:false "NAME" pod)
167 pr "struct command_entry %s_cmd_entry = {\n" name;
168 pr " .name = \"%s\",\n" name2;
169 pr " .help = \"%s\",\n" (c_quote text);
170 pr " .run = run_%s\n" name;
175 (* list_commands function, which implements guestfish -h *)
177 pr "list_commands (void)\n";
179 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
180 pr " list_builtin_commands ();\n";
182 fun (name, _, _, flags, _, shortdesc, _) ->
183 let name = replace_char name '_' '-' in
184 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
186 ) all_functions_and_fish_commands_sorted;
187 pr " printf (\" %%s\\n\",";
188 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
192 (* display_command function, which implements guestfish -h cmd *)
194 pr "display_command (const char *cmd)\n";
196 pr " const struct command_table *ct;\n";
198 pr " ct = lookup_fish_command (cmd, strlen (cmd));\n";
200 pr " fputs (ct->entry->help, stdout);\n";
204 pr " return display_builtin_command (cmd);\n";
208 let emit_print_list_function typ =
210 pr "print_%s_list (struct guestfs_%s_list *%ss)\n"
213 pr " unsigned int i;\n";
215 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
216 pr " printf (\"[%%d] = {\\n\", i);\n";
217 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
218 pr " printf (\"}\\n\");\n";
224 (* print_* functions *)
228 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
231 pr "print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
234 pr " unsigned int i;\n";
240 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
242 pr " printf (\"%%s%s: \", indent);\n" name;
243 pr " for (i = 0; i < 32; ++i)\n";
244 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
245 pr " printf (\"\\n\");\n"
247 pr " printf (\"%%s%s: \", indent);\n" name;
248 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
249 pr " if (c_isprint (%s->%s[i]))\n" typ name;
250 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
252 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
253 pr " printf (\"\\n\");\n"
254 | name, (FUInt64|FBytes) ->
255 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
258 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
261 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
264 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
267 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
269 | name, FOptPercent ->
270 pr " if (%s->%s >= 0)\n" typ name;
271 pr " printf (\"%%s%s: %%g %%%%\\n\", indent, (double) %s->%s);\n"
274 pr " printf (\"%%s%s: \\n\", indent);\n" name
280 (* Emit a print_TYPE_list function definition only if that function is used. *)
283 | typ, (RStructListOnly | RStructAndList) ->
284 (* generate the function for typ *)
285 emit_print_list_function typ
286 | typ, _ -> () (* empty *)
287 ) (rstructs_used_by all_functions);
289 (* Emit a print_TYPE function definition only if that function is used. *)
292 | typ, (RStructOnly | RStructAndList) ->
294 pr "print_%s (struct guestfs_%s *%s)\n" typ typ typ;
296 pr " print_%s_indent (%s, \"\");\n" typ typ;
299 | typ, _ -> () (* empty *)
300 ) (rstructs_used_by all_functions);
302 (* run_<action> actions *)
304 fun (name, (ret, args, optargs as style), _, flags, _, _, _) ->
306 pr "run_%s (const char *cmd, size_t argc, char *argv[])\n" name;
311 | RBool _ -> pr " int r;\n"
312 | RInt64 _ -> pr " int64_t r;\n"
313 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
314 | RString _ -> pr " char *r;\n"
315 | RStringList _ | RHashtable _ -> pr " char **r;\n"
316 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
317 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
320 pr " size_t size;\n";
326 | OptString n -> pr " const char *%s;\n" n
331 | Key n -> pr " char *%s;\n" n
333 pr " const char *%s;\n" n;
334 pr " size_t %s_size;\n" n
335 | StringList n | DeviceList n -> pr " char **%s;\n" n
336 | Bool n -> pr " int %s;\n" n
337 | Int n -> pr " int %s;\n" n
338 | Int64 n -> pr " int64_t %s;\n" n
339 | Pointer _ -> assert false
342 if optargs <> [] then (
343 pr " struct guestfs_%s_argv optargs_s = { .bitmask = 0 };\n" name;
344 pr " struct guestfs_%s_argv *optargs = &optargs_s;\n" name
347 if args <> [] || optargs <> [] then
348 pr " size_t i = 0;\n";
352 (* Check and convert parameters. *)
353 let argc_minimum, argc_maximum =
355 List.filter (function Key _ -> false | _ -> true) args in
356 let argc_minimum = List.length args_no_keys in
357 let argc_maximum = argc_minimum + List.length optargs in
358 argc_minimum, argc_maximum in
360 if argc_minimum = argc_maximum then (
361 pr " if (argc != %d) {\n" argc_minimum;
362 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
365 pr " if (argc < %d || argc > %d) {\n" argc_minimum argc_maximum;
366 pr " fprintf (stderr, _(\"%%s should have %%d-%%d parameter(s)\\n\"), cmd, %d, %d);\n"
367 argc_minimum argc_maximum;
369 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
373 let parse_integer expr fn fntyp rtyp range name =
375 pr " strtol_error xerr;\n";
378 pr " xerr = %s (%s, NULL, 0, &r, xstrtol_suffixes);\n" fn expr;
379 pr " if (xerr != LONGINT_OK) {\n";
380 pr " fprintf (stderr,\n";
381 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
382 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
387 | Some (min, max, comment) ->
388 pr " /* %s */\n" comment;
389 pr " if (r < %s || r > %s) {\n" min max;
390 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
394 pr " /* The check above should ensure this assignment does not overflow. */\n";
396 pr " %s = r;\n" name;
404 pr " %s = argv[i++];\n" name
406 | Dev_or_Path name ->
407 pr " %s = win_prefix (argv[i++]); /* process \"win:\" prefix */\n" name;
408 pr " if (%s == NULL) return -1;\n" name
410 pr " %s = STRNEQ (argv[i], \"\") ? argv[i] : NULL;\n" name;
413 pr " %s = argv[i];\n" name;
414 pr " %s_size = strlen (argv[i]);\n" name;
417 pr " %s = file_in (argv[i++]);\n" name;
418 pr " if (%s == NULL) return -1;\n" name
420 pr " %s = file_out (argv[i++]);\n" name;
421 pr " if (%s == NULL) return -1;\n" name
422 | StringList name | DeviceList name ->
423 pr " %s = parse_string_list (argv[i++]);\n" name;
424 pr " if (%s == NULL) return -1;\n" name
426 pr " %s = read_key (\"%s\");\n" name name;
427 pr " if (keys_from_stdin)\n";
428 pr " input_lineno++;\n";
429 pr " if (%s == NULL) return -1;\n" name
431 pr " %s = is_true (argv[i++]) ? 1 : 0;\n" name
434 let min = "(-(2LL<<30))"
435 and max = "((2LL<<30)-1)"
437 "The Int type in the generator is a signed 31 bit int." in
438 Some (min, max, comment) in
439 parse_integer "argv[i++]" "xstrtoll" "long long" "int" range name
441 parse_integer "argv[i++]" "xstrtoll" "long long" "int64_t" None name
442 | Pointer _ -> assert false
445 (* Optional arguments are prefixed with <argname>:<value> and
446 * may be missing, so we need to parse those until the end of
449 if optargs <> [] then (
450 let uc_name = String.uppercase name in
452 pr " for (; i < argc; ++i) {\n";
453 pr " uint64_t this_mask;\n";
454 pr " const char *this_arg;\n";
459 let n = name_of_optargt argt in
460 let uc_n = String.uppercase n in
461 let len = String.length n in
462 pr "if (STRPREFIX (argv[i], \"%s:\")) {\n" n;
465 pr " optargs_s.%s = is_true (&argv[i][%d]) ? 1 : 0;\n"
469 let min = "(-(2LL<<30))"
470 and max = "((2LL<<30)-1)"
472 "The Int type in the generator is a signed 31 bit int." in
473 Some (min, max, comment) in
474 let expr = sprintf "&argv[i][%d]" (len+1) in
475 parse_integer expr "xstrtoll" "long long" "int" range
476 (sprintf "optargs_s.%s" n)
478 let expr = sprintf "&argv[i][%d]" (len+1) in
479 parse_integer expr "xstrtoll" "long long" "int64_t" None
480 (sprintf "optargs_s.%s" n)
482 pr " optargs_s.%s = &argv[i][%d];\n" n (len+1);
484 pr " this_mask = GUESTFS_%s_%s_BITMASK;\n" uc_name uc_n;
485 pr " this_arg = \"%s\";\n" n;
491 pr " fprintf (stderr, _(\"%%s: unknown optional argument \\\"%%s\\\"\\n\"),\n";
492 pr " cmd, argv[i]);\n";
496 pr " if (optargs_s.bitmask & this_mask) {\n";
497 pr " fprintf (stderr, _(\"%%s: optional argument \\\"%%s\\\" given twice\\n\"),\n";
498 pr " cmd, this_arg);\n";
501 pr " optargs_s.bitmask |= this_mask;\n";
506 (* Call C API function. *)
508 pr " r = guestfs_%s " name
510 pr " r = guestfs_%s_argv " name;
511 generate_c_call_args ~handle:"g" style;
516 | Device _ | String _
517 | OptString _ | Bool _
520 | Pathname name | Dev_or_Path name | FileOut name
522 pr " free (%s);\n" name
524 pr " free_file_in (%s);\n" name
525 | StringList name | DeviceList name ->
526 pr " free_strings (%s);\n" name
527 | Pointer _ -> assert false
530 (* Any output flags? *)
532 let flags = filter_map (
533 function FishOutput flag -> Some flag | _ -> None
539 failwithf "%s: more than one FishOutput flag is not allowed" name in
541 (* Check return value for errors and display command results. *)
543 | RErr -> pr " return r;\n"
545 pr " if (r == -1) return -1;\n";
546 (match fish_output with
548 pr " printf (\"%%d\\n\", r);\n";
549 | Some FishOutputOctal ->
550 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
551 | Some FishOutputHexadecimal ->
552 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
555 pr " if (r == -1) return -1;\n";
556 (match fish_output with
558 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
559 | Some FishOutputOctal ->
560 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
561 | Some FishOutputHexadecimal ->
562 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
565 pr " if (r == -1) return -1;\n";
566 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
569 pr " if (r == NULL) return -1;\n";
570 pr " printf (\"%%s\\n\", r);\n";
572 | RConstOptString _ ->
573 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
576 pr " if (r == NULL) return -1;\n";
577 pr " printf (\"%%s\\n\", r);\n";
581 pr " if (r == NULL) return -1;\n";
582 pr " print_strings (r);\n";
583 pr " free_strings (r);\n";
585 | RStruct (_, typ) ->
586 pr " if (r == NULL) return -1;\n";
587 pr " print_%s (r);\n" typ;
588 pr " guestfs_free_%s (r);\n" typ;
590 | RStructList (_, typ) ->
591 pr " if (r == NULL) return -1;\n";
592 pr " print_%s_list (r);\n" typ;
593 pr " guestfs_free_%s_list (r);\n" typ;
596 pr " if (r == NULL) return -1;\n";
597 pr " print_table (r);\n";
598 pr " free_strings (r);\n";
601 pr " if (r == NULL) return -1;\n";
602 pr " if (full_write (1, r, size) != size) {\n";
603 pr " perror (\"write\");\n";
614 (* run_action function *)
616 pr "run_action (const char *cmd, size_t argc, char *argv[])\n";
618 pr " const struct command_table *ct;\n";
620 pr " ct = lookup_fish_command (cmd, strlen (cmd));\n";
622 pr " return ct->entry->run (cmd, argc, argv);\n";
624 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
625 pr " if (command_num == 1)\n";
626 pr " extended_help_message ();\n";
631 and generate_fish_cmds_h () =
632 generate_header CStyle GPLv2plus;
634 pr "#ifndef FISH_CMDS_H\n";
635 pr "#define FISH_CMDS_H\n";
639 fun (shortname, _, _, _, _, _, _) ->
640 pr "extern int run_%s (const char *cmd, size_t argc, char *argv[]);\n"
645 pr "#endif /* FISH_CMDS_H */\n"
647 (* gperf code to do fast lookups of commands. *)
648 and generate_fish_cmds_gperf () =
649 generate_header CStyle GPLv2plus;
651 let all_functions_sorted =
653 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
654 ) all_functions_sorted in
656 let all_functions_and_fish_commands_sorted =
657 List.sort action_compare (all_functions_sorted @ fish_commands) in
661 %%define lookup-function-name lookup_fish_command
673 #include \"cmds_gperf.h\"
678 fun (name, _, _, _, _, _, _) ->
679 pr "extern struct command_entry %s_cmd_entry;\n" name
680 ) all_functions_and_fish_commands_sorted;
685 struct command_table;
691 fun (name, _, _, flags, _, _, _) ->
692 let name2 = replace_char name '_' '-' in
694 filter_map (function FishAlias n -> Some n | _ -> None) flags in
696 (* The basic command. *)
697 pr "%s, &%s_cmd_entry\n" name name;
699 (* Command with dashes instead of underscores. *)
700 if name <> name2 then
701 pr "%s, &%s_cmd_entry\n" name2 name;
703 (* Aliases for the command. *)
706 pr "%s, &%s_cmd_entry\n" alias name;
708 ) all_functions_and_fish_commands_sorted
710 (* Readline completion for guestfish. *)
711 and generate_fish_completion () =
712 generate_header CStyle GPLv2plus;
716 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
726 #ifdef HAVE_LIBREADLINE
727 #include <readline/readline.h>
732 #ifdef HAVE_LIBREADLINE
734 static const char *const commands[] = {
735 BUILTIN_COMMANDS_FOR_COMPLETION,
738 (* Get the commands, including the aliases. They don't need to be
739 * sorted - the generator() function just does a dumb linear search.
743 fun (name, _, _, flags, _, _, _) ->
744 let name2 = replace_char name '_' '-' in
746 filter_map (function FishAlias n -> Some n | _ -> None) flags in
748 ) (all_functions @ fish_commands) in
749 let commands = List.flatten commands in
751 List.iter (pr " \"%s\",\n") commands;
757 generator (const char *text, int state)
759 static size_t index, len;
767 rl_attempted_completion_over = 1;
769 while ((name = commands[index]) != NULL) {
771 if (STRCASEEQLEN (name, text, len))
772 return strdup (name);
778 #endif /* HAVE_LIBREADLINE */
780 #ifdef HAVE_RL_COMPLETION_MATCHES
781 #define RL_COMPLETION_MATCHES rl_completion_matches
783 #ifdef HAVE_COMPLETION_MATCHES
784 #define RL_COMPLETION_MATCHES completion_matches
786 #endif /* else just fail if we don't have either symbol */
789 do_completion (const char *text, int start, int end)
791 char **matches = NULL;
793 #ifdef HAVE_LIBREADLINE
794 rl_completion_append_character = ' ';
797 matches = RL_COMPLETION_MATCHES (text, generator);
798 else if (complete_dest_paths)
799 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
806 (* Generate the POD documentation for guestfish. *)
807 and generate_fish_actions_pod () =
808 let all_functions_sorted =
810 fun (_, _, _, flags, _, _, _) ->
811 not (List.mem NotInFish flags || List.mem NotInDocs flags)
812 ) all_functions_sorted in
814 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
817 fun (name, (_, args, optargs), _, flags, _, _, longdesc) ->
819 Str.global_substitute rex (
822 try Str.matched_group 1 s
824 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
825 "L</" ^ replace_char sub '_' '-' ^ ">"
827 let name = replace_char name '_' '-' in
829 filter_map (function FishAlias n -> Some n | _ -> None) flags in
833 pr "=head2 %s\n\n" name
838 | Pathname n | Device n | Dev_or_Path n | String n ->
840 | OptString n -> pr " %s" n
841 | StringList n | DeviceList n -> pr " '%s ...'" n
842 | Bool _ -> pr " true|false"
843 | Int n -> pr " %s" n
844 | Int64 n -> pr " %s" n
845 | FileIn n | FileOut n -> pr " (%s|-)" n
846 | BufferIn n -> pr " %s" n
847 | Key _ -> () (* keys are entered at a prompt *)
848 | Pointer _ -> assert false
852 | (OBool n | OInt n | OInt64 n | OString n) as arg ->
853 pr " [%s:%s]" n (doc_opttype_of arg)
857 pr "%s\n\n" longdesc;
859 if List.exists (function FileIn _ | FileOut _ -> true
860 | _ -> false) args then
861 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
863 if List.exists (function Key _ -> true | _ -> false) args then
864 pr "This command has one or more key or passphrase parameters.
865 Guestfish will prompt for these separately.\n\n";
867 if optargs <> [] then
868 pr "This command has one or more optional arguments. See L</OPTIONAL ARGUMENTS>.\n\n";
870 if List.mem ProtocolLimitWarning flags then
871 pr "%s\n\n" protocol_limit_warning;
873 match deprecation_notice flags with
875 | Some txt -> pr "%s\n\n" txt
876 ) all_functions_sorted
878 (* Generate documentation for guestfish-only commands. *)
879 and generate_fish_commands_pod () =
881 fun (name, _, _, flags, _, _, longdesc) ->
882 let name = replace_char name '_' '-' in
884 filter_map (function FishAlias n -> Some n | _ -> None) flags in
888 pr "=head2 %s\n\n" name
890 pr "%s\n\n" longdesc;
893 and generate_fish_prep_options_h () =
894 generate_header CStyle GPLv2plus;
896 pr "#ifndef PREPOPTS_H\n";
901 const char *name; /* eg. \"fs\" */
903 size_t nr_params; /* optional parameters */
904 struct prep_param *params;
906 const char *shortdesc; /* short description */
907 const char *longdesc; /* long description */
909 /* functions to implement it */
910 void (*prelaunch) (const char *filename, prep_data *);
911 void (*postlaunch) (const char *filename, prep_data *, const char *device);
915 const char *pname; /* parameter name */
916 const char *pdefault; /* parameter default */
917 const char *pdesc; /* parameter description */
920 extern const struct prep preps[];
923 " (List.length prepopts);
926 fun (name, shortdesc, args, longdesc) ->
928 extern void prep_prelaunch_%s (const char *filename, prep_data *data);
929 extern void prep_postlaunch_%s (const char *filename, prep_data *data, const char *device);
935 pr "#endif /* PREPOPTS_H */\n"
937 and generate_fish_prep_options_c () =
938 generate_header CStyle GPLv2plus;
944 #include \"prepopts.h\"
949 fun (name, shortdesc, args, longdesc) ->
950 pr "static struct prep_param %s_args[] = {\n" name;
952 fun (n, default, desc) ->
953 pr " { \"%s\", \"%s\", \"%s\" },\n" n default desc
959 pr "const struct prep preps[] = {\n";
961 fun (name, shortdesc, args, longdesc) ->
962 pr " { \"%s\", %d, %s_args,
965 prep_prelaunch_%s, prep_postlaunch_%s },
967 name (List.length args) name
968 (c_quote shortdesc) (c_quote longdesc)
973 and generate_fish_event_names () =
974 generate_header CStyle GPLv2plus;
984 event_name_of_event_bitmask (uint64_t ev)
991 pr " case GUESTFS_EVENT_%s:\n" (String.uppercase name);
992 pr " return \"%s\";\n" name
996 abort (); /* should not happen */
1001 print_event_set (uint64_t event_bitmask, FILE *fp)
1005 if (event_bitmask == GUESTFS_EVENT_ALL) {
1014 pr " if (event_bitmask & GUESTFS_EVENT_%s) {\n" (String.uppercase name);
1015 pr " if (comma) fputc (',', fp);\n";
1017 pr " fputs (\"%s\", fp);\n" name;
1025 event_bitmask_of_event_set (const char *arg, uint64_t *eventset_r)
1029 if (STREQ (arg, \"*\")) {
1030 *eventset_r = GUESTFS_EVENT_ALL;
1037 n = strcspn (arg, \",\");
1043 pr "if (STREQLEN (arg, \"%s\", n))\n" name;
1044 pr " *eventset_r |= GUESTFS_EVENT_%s;\n" (String.uppercase name);
1050 fprintf (stderr, _(\"unknown event name: %%s\\n\"), arg);