X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=generator%2Fgenerator_fish.ml;h=c5def5c9bf44406b9bf12c34eb8a2ad82bbc87bb;hp=fdb4eff39057c830884f40bc6403d027307f8e1a;hb=319e946b92e175c05cdd1fdcb85c9b86f5631011;hpb=14490c3e1aac61c6ac90f28828896683f64f0dc9 diff --git a/generator/generator_fish.ml b/generator/generator_fish.ml index fdb4eff..c5def5c 100644 --- a/generator/generator_fish.ml +++ b/generator/generator_fish.ml @@ -48,6 +48,9 @@ let generate_fish_cmds () = pr "#include \n"; pr "\n"; + pr "/* It is safe to call deprecated functions from this file. */\n"; + pr "#undef GUESTFS_WARN_DEPRECATED\n"; + pr "\n"; pr "#include \n"; pr "#include \n"; pr "#include \n"; @@ -58,31 +61,22 @@ let generate_fish_cmds () = pr "#include \"full-write.h\"\n"; pr "#include \"xstrtol.h\"\n"; pr "#include \"fish.h\"\n"; + pr "#include \"options.h\"\n"; + pr "#include \"cmds_gperf.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"; - (* list_commands function, which implements guestfish -h *) - pr "void list_commands (void)\n"; - pr "{\n"; - pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n"; - pr " list_builtin_commands ();\n"; List.iter ( - fun (name, _, _, flags, _, shortdesc, _) -> - let name = replace_char name '_' '-' in - pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n" - name shortdesc - ) all_functions_and_fish_commands_sorted; - pr " printf (\" %%s\\n\","; - pr " _(\"Use -h / help to show detailed help for a command.\"));\n"; - pr "}\n"; - pr "\n"; + fun (name, _, _, _, _, _, _) -> + pr "static int run_%s (const char *cmd, size_t argc, char *argv[]);\n" + name + ) all_functions; - (* display_command function, which implements guestfish -h cmd *) - pr "int display_command (const char *cmd)\n"; - pr "{\n"; + pr "\n"; + (* List of command_entry structs. *) List.iter ( fun (name, _, _, flags, _, shortdesc, longdesc) -> let name2 = replace_char name '_' '-' in @@ -94,22 +88,19 @@ let generate_fish_cmds () = (String.concat " or " (List.map (fun s -> "'" ^ s ^ "'") aliases)) else "" in - pr " if ("; - pr "STRCASEEQ (cmd, \"%s\")" name; - if name <> name2 then - pr " || STRCASEEQ (cmd, \"%s\")" name2; - List.iter ( - fun alias -> - pr " || STRCASEEQ (cmd, \"%s\")" alias - ) aliases; - pr ") {\n"; - pr " pod2text (\"%s\", _(\"%s\"), %S);\n" - name2 shortdesc - ("=head1 DESCRIPTION\n\n" ^ - longdesc ^ describe_alias); - pr " return 0;\n"; - pr " }\n"; - pr " else\n" + 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_quote text); + pr " .run = run_%s\n" name; + pr "};\n"; + pr "\n"; ) fish_commands; List.iter ( @@ -117,6 +108,7 @@ let generate_fish_cmds () = let name2 = replace_char name '_' '-' in let aliases = filter_map (function FishAlias n -> Some n | _ -> None) flags in + let longdesc = replace_str longdesc "C "'" ^ s ^ "'") aliases)) else "" in - pr " if ("; - pr "STRCASEEQ (cmd, \"%s\")" name; - if name <> name2 then - pr " || STRCASEEQ (cmd, \"%s\")" name2; - List.iter ( - fun alias -> - pr " || STRCASEEQ (cmd, \"%s\")" alias - ) aliases; - pr ") {\n"; - pr " pod2text (\"%s\", _(\"%s\"), %S);\n" - name2 shortdesc - ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^ - "=head1 DESCRIPTION\n\n" ^ - longdesc ^ warnings ^ describe_alias); - pr " return 0;\n"; - pr " }\n"; - pr " else\n" + 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_quote text); + pr " .run = run_%s\n" name; + pr "};\n"; + pr "\n"; ) all_functions; + (* list_commands function, which implements guestfish -h *) + pr "void list_commands (void)\n"; + pr "{\n"; + pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n"; + pr " list_builtin_commands ();\n"; + List.iter ( + fun (name, _, _, flags, _, shortdesc, _) -> + let name = replace_char name '_' '-' in + pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n" + name shortdesc + ) all_functions_and_fish_commands_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 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"; @@ -279,7 +294,8 @@ Guestfish will prompt for these separately." (* run_ actions *) List.iter ( fun (name, (ret, args, optargs as style), _, flags, _, _, _) -> - pr "static int run_%s (const char *cmd, size_t argc, char *argv[])\n" name; + pr "static int\n"; + pr "run_%s (const char *cmd, size_t argc, char *argv[])\n" name; pr "{\n"; (match ret with | RErr @@ -312,6 +328,7 @@ Guestfish will prompt for these separately." | Bool n -> pr " int %s;\n" n | Int n -> pr " int %s;\n" n | Int64 n -> pr " int64_t %s;\n" n + | Pointer _ -> assert false ) args; if optargs <> [] then ( @@ -379,7 +396,7 @@ Guestfish will prompt for these separately." pr " %s = argv[i++];\n" name | Pathname name | Dev_or_Path name -> - pr " %s = resolve_win_path (argv[i++]);\n" name; + pr " %s = win_prefix (argv[i++]); /* process \"win:\" prefix */\n" name; pr " if (%s == NULL) return -1;\n" name | OptString name -> pr " %s = STRNEQ (argv[i], \"\") ? argv[i] : NULL;\n" name; @@ -399,6 +416,8 @@ Guestfish will prompt for these separately." pr " if (%s == NULL) return -1;\n" name | Key name -> pr " %s = read_key (\"%s\");\n" name name; + pr " if (keys_from_stdin)\n"; + pr " input_lineno++;\n"; pr " if (%s == NULL) return -1;\n" name | Bool name -> pr " %s = is_true (argv[i++]) ? 1 : 0;\n" name @@ -412,6 +431,7 @@ Guestfish will prompt for these separately." parse_integer "argv[i++]" "xstrtoll" "long long" "int" range name | Int64 name -> parse_integer "argv[i++]" "xstrtoll" "long long" "int64_t" None name + | Pointer _ -> assert false ) args; (* Optional arguments are prefixed with : and @@ -424,12 +444,14 @@ Guestfish will prompt for these separately." pr " for (; i < argc; ++i) {\n"; pr " uint64_t this_mask;\n"; pr " const char *this_arg;\n"; + pr "\n"; + pr " "; List.iter ( fun argt -> let n = name_of_argt argt in let uc_n = String.uppercase n in let len = String.length n in - pr " if (STRPREFIX (argv[i], \"%s:\")) {\n" n; + pr "if (STRPREFIX (argv[i], \"%s:\")) {\n" n; (match argt with | Bool n -> pr " optargs_s.%s = is_true (&argv[i][%d]) ? 1 : 0;\n" @@ -442,10 +464,12 @@ Guestfish will prompt for these separately." "The Int type in the generator is a signed 31 bit int." in Some (min, max, comment) in let expr = sprintf "&argv[i][%d]" (len+1) in - parse_integer expr "xstrtoll" "long long" "int" range name + parse_integer expr "xstrtoll" "long long" "int" range + (sprintf "optargs_s.%s" n) | Int64 n -> let expr = sprintf "&argv[i][%d]" (len+1) in - parse_integer expr "xstrtoll" "long long" "int64_t" None name + parse_integer expr "xstrtoll" "long long" "int64_t" None + (sprintf "optargs_s.%s" n) | String n -> pr " optargs_s.%s = &argv[i][%d];\n" n (len+1); | _ -> assert false @@ -453,10 +477,17 @@ Guestfish will prompt for these separately." pr " this_mask = GUESTFS_%s_%s_BITMASK;\n" uc_name uc_n; pr " this_arg = \"%s\";\n" n; pr " }\n"; + pr " else "; ) optargs; + pr "{\n"; + pr " fprintf (stderr, _(\"%%s: unknown optional argument \\\"%%s\\\"\\n\"),\n"; + pr " cmd, argv[i]);\n"; + pr " return -1;\n"; + pr " }\n"; + pr "\n"; pr " if (optargs_s.bitmask & this_mask) {\n"; - pr " fprintf (stderr, _(\"%%s: optional argument %%s given twice\\n\"),\n"; + pr " fprintf (stderr, _(\"%%s: optional argument \\\"%%s\\\" given twice\\n\"),\n"; pr " cmd, this_arg);\n"; pr " return -1;\n"; pr " }\n"; @@ -486,6 +517,7 @@ Guestfish will prompt for these separately." pr " free_file_in (%s);\n" name | StringList name | DeviceList name -> pr " free_strings (%s);\n" name + | Pointer _ -> assert false ) args; (* Any output flags? *) @@ -573,36 +605,84 @@ Guestfish will prompt for these separately." ) all_functions; (* run_action function *) - pr "int run_action (const char *cmd, size_t argc, char *argv[])\n"; + pr "int\n"; + pr "run_action (const char *cmd, size_t argc, char *argv[])\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 " return ct->entry->run (cmd, argc, argv);\n"; + pr " else {\n"; + pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n"; + pr " if (command_num == 1)\n"; + pr " extended_help_message ();\n"; + pr " return -1;\n"; + pr " }\n"; + pr "}\n" + +(* gperf code to do fast lookups of commands. *) +and generate_fish_cmds_gperf () = + generate_header CStyle GPLv2plus; + + let all_functions_sorted = + List.filter ( + fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags) + ) all_functions_sorted in + + let all_functions_and_fish_commands_sorted = + List.sort action_compare (all_functions_sorted @ fish_commands) in + + pr "\ +%%language=ANSI-C +%%define lookup-function-name lookup_fish_command +%%ignore-case +%%readonly-tables +%%null-strings + +%%{ + +#include + +#include +#include + +#include \"cmds_gperf.h\" + +"; + + List.iter ( + fun (name, _, _, _, _, _, _) -> + pr "extern struct command_entry %s_cmd_entry;\n" name + ) all_functions_and_fish_commands_sorted; + + pr "\ +%%} + +struct command_table; + +%%%% +"; List.iter ( fun (name, _, _, flags, _, _, _) -> let name2 = replace_char name '_' '-' in let aliases = filter_map (function FishAlias n -> Some n | _ -> None) flags in - pr " if ("; - pr "STRCASEEQ (cmd, \"%s\")" name; + + (* The basic command. *) + pr "%s, &%s_cmd_entry\n" name name; + + (* Command with dashes instead of underscores. *) if name <> name2 then - pr " || STRCASEEQ (cmd, \"%s\")" name2; + pr "%s, &%s_cmd_entry\n" name2 name; + + (* Aliases for the command. *) List.iter ( fun alias -> - pr " || STRCASEEQ (cmd, \"%s\")" alias; + pr "%s, &%s_cmd_entry\n" alias name; ) aliases; - pr ")\n"; - pr " return run_%s (cmd, argc, argv);\n" name; - pr " else\n"; - ) all_functions_and_fish_commands_sorted; - - pr " {\n"; - pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n"; - pr " if (command_num == 1)\n"; - pr " extended_help_message ();\n"; - pr " return -1;\n"; - pr " }\n"; - pr " return 0;\n"; - pr "}\n"; - pr "\n" + ) all_functions_and_fish_commands_sorted (* Readline completion for guestfish. *) and generate_fish_completion () = @@ -742,6 +822,7 @@ and generate_fish_actions_pod () = | FileIn n | FileOut n -> pr " (%s|-)" n | BufferIn n -> pr " %s" n | Key _ -> () (* keys are entered at a prompt *) + | Pointer _ -> assert false ) args; List.iter ( function @@ -837,6 +918,8 @@ and generate_fish_prep_options_c () = generate_header CStyle GPLv2plus; pr "\ +#include + #include \"fish.h\" #include \"prepopts.h\"