+ parse_integer "argv[i++]" "xstrtoll" "long long" "int64_t" None name
+ ) args;
+
+ (* Optional arguments are prefixed with <argname>:<value> and
+ * may be missing, so we need to parse those until the end of
+ * the argument list.
+ *)
+ if optargs <> [] then (
+ let uc_name = String.uppercase name in
+ pr "\n";
+ 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;
+ (match argt with
+ | Bool n ->
+ pr " optargs_s.%s = is_true (&argv[i][%d]) ? 1 : 0;\n"
+ n (len+1);
+ | Int n ->
+ let range =
+ let min = "(-(2LL<<30))"
+ and max = "((2LL<<30)-1)"
+ and comment =
+ "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
+ | Int64 n ->
+ let expr = sprintf "&argv[i][%d]" (len+1) in
+ parse_integer expr "xstrtoll" "long long" "int64_t" None name
+ | String n ->
+ pr " optargs_s.%s = &argv[i][%d];\n" n (len+1);
+ | _ -> assert false
+ );
+ 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 " cmd, this_arg);\n";
+ pr " return -1;\n";
+ pr " }\n";
+ pr " optargs_s.bitmask |= this_mask;\n";
+ pr " }\n";
+ pr "\n";
+ );