📄 argp-help.c
字号:
/* Put CHILD->argp within its own cluster. */ ? hol_add_cluster (hol, child->group, child->header, child - argp->children, cluster, argp) /* Just merge it into the parent's cluster. */ : cluster); hol_append (hol, argp_hol (child->argp, child_cluster)) ; child++; } return hol;}/* Calculate how many different levels with alternative args strings exist in ARGP. */static size_targp_args_levels (const struct argp *argp){ size_t levels = 0; const struct argp_child *child = argp->children; if (argp->args_doc && strchr (argp->args_doc, '\n')) levels++; if (child) while (child->argp) levels += argp_args_levels ((child++)->argp); return levels;}/* Print all the non-option args documented in ARGP to STREAM. Any output is preceded by a space. LEVELS is a pointer to a byte vector the length returned by argp_args_levels; it should be initialized to zero, and updated by this routine for the next call if ADVANCE is true. True is returned as long as there are more patterns to output. */static intargp_args_usage (const struct argp *argp, char **levels, int advance, argp_fmtstream_t stream){ char *our_level = *levels; int multiple = 0; const struct argp_child *child = argp->children; const char *doc = gettext (argp->args_doc), *nl = 0; if (doc) { nl = strchr (doc, '\n'); if (nl) /* This is a `multi-level' args doc; advance to the correct position as determined by our state in LEVELS, and update LEVELS. */ { int i; multiple = 1; for (i = 0; i < *our_level; i++) doc = nl + 1, nl = strchr (doc, '\n'); (*levels)++; } if (! nl) nl = doc + strlen (doc); /* Manually do line wrapping so that it (probably) won't get wrapped at any embedded spaces. */ space (stream, 1 + nl - doc); __argp_fmtstream_write (stream, doc, nl - doc); } if (child) while (child->argp) advance = !argp_args_usage ((child++)->argp, levels, advance, stream); if (advance && multiple) /* Need to increment our level. */ if (*nl) /* There's more we can do here. */ { (*our_level)++; advance = 0; /* Our parent shouldn't advance also. */ } else if (*our_level > 0) /* We had multiple levels, but used them up; reset to zero. */ *our_level = 0; return !advance;}/* Print the documentation for ARGP to STREAM; if POST is false, then everything preceeding a `\v' character in the documentation strings (or the whole string, for those with none) is printed, otherwise, everything following the `\v' character (nothing for strings without). Each separate bit of documentation is separated a blank line, and if PRE_BLANK is true, then the first is as well. If FIRST_ONLY is true, only the first occurance is output. Returns true if anything was output. */static intargp_doc (const struct argp *argp, const struct argp_state *state, int post, int pre_blank, int first_only, argp_fmtstream_t stream){ const char *text; const char *inp_text; void *input = 0; int anything = 0; size_t inp_text_limit = 0; const char *doc = gettext (argp->doc); const struct argp_child *child = argp->children; if (doc) { char *vt = strchr (doc, '\v'); inp_text = post ? (vt ? vt + 1 : 0) : doc; inp_text_limit = (!post && vt) ? (vt - doc) : 0; } else inp_text = 0; if (argp->help_filter) /* We have to filter the doc strings. */ { if (inp_text_limit) /* Copy INP_TEXT so that it's nul-terminated. */ inp_text = strndup (inp_text, inp_text_limit); input = __argp_input (argp, state); text = (*argp->help_filter) (post ? ARGP_KEY_HELP_POST_DOC : ARGP_KEY_HELP_PRE_DOC, inp_text, input); } else text = (const char *) inp_text; if (text) { if (pre_blank) __argp_fmtstream_putc (stream, '\n'); if (text == inp_text && inp_text_limit) __argp_fmtstream_write (stream, inp_text, inp_text_limit); else __argp_fmtstream_puts (stream, text); if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream)) __argp_fmtstream_putc (stream, '\n'); anything = 1; } if (text && text != inp_text) free ((char *) text); /* Free TEXT returned from the help filter. */ if (inp_text && inp_text_limit && argp->help_filter) free ((char *) inp_text); /* We copied INP_TEXT, so free it now. */ if (post && argp->help_filter) /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text. */ { text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input); if (text) { if (anything || pre_blank) __argp_fmtstream_putc (stream, '\n'); __argp_fmtstream_puts (stream, text); free ((char *) text); if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream)) __argp_fmtstream_putc (stream, '\n'); anything = 1; } } if (child) while (child->argp && !(first_only && anything)) anything |= argp_doc ((child++)->argp, state, post, anything || pre_blank, first_only, stream); return anything;}/* Output a usage message for ARGP to STREAM. If called from argp_state_help, STATE is the relevent parsing state. FLAGS are from the set ARGP_HELP_*. NAME is what to use wherever a `program name' is needed. */static void_help (const struct argp *argp, const struct argp_state *state, FILE *stream, unsigned flags, char *name){ int anything = 0; /* Whether we've output anything. */ struct hol *hol = 0; argp_fmtstream_t fs; if (! stream) return; if (! uparams.valid) fill_in_uparams (state); fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0); if (! fs) return; if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG)) { hol = argp_hol (argp, 0); /* If present, these options always come last. */ hol_set_group (hol, "help", -1); hol_set_group (hol, "version", -1); hol_sort (hol); } if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE)) /* Print a short `Usage:' message. */ { int first_pattern = 1, more_patterns; size_t num_pattern_levels = argp_args_levels (argp); char *pattern_levels = alloca (num_pattern_levels); memset (pattern_levels, 0, num_pattern_levels); do { int old_lm; int old_wm = __argp_fmtstream_set_wmargin (fs, USAGE_INDENT); char *levels = pattern_levels; __argp_fmtstream_printf (fs, "%s %s", _(first_pattern ? "Usage:" : " or: "), name); /* We set the lmargin as well as the wmargin, because hol_usage manually wraps options with newline to avoid annoying breaks. */ old_lm = __argp_fmtstream_set_lmargin (fs, USAGE_INDENT); if (flags & ARGP_HELP_SHORT_USAGE) /* Just show where the options go. */ { if (hol->num_entries > 0) __argp_fmtstream_puts (fs, _(" [OPTION...]")); } else /* Actually print the options. */ { hol_usage (hol, fs); flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once. */ } more_patterns = argp_args_usage (argp, &levels, 1, fs); __argp_fmtstream_set_wmargin (fs, old_wm); __argp_fmtstream_set_lmargin (fs, old_lm); __argp_fmtstream_putc (fs, '\n'); anything = 1; first_pattern = 0; } while (more_patterns); } if (flags & ARGP_HELP_PRE_DOC) anything |= argp_doc (argp, state, 0, 0, 1, fs); if (flags & ARGP_HELP_SEE) { __argp_fmtstream_printf (fs, _("\Try `%s --help' or `%s --usage' for more information.\n"), name, name); anything = 1; } if (flags & ARGP_HELP_LONG) /* Print a long, detailed help message. */ { /* Print info about all the options. */ if (hol->num_entries > 0) { if (anything) __argp_fmtstream_putc (fs, '\n'); hol_help (hol, state, fs); anything = 1; } } if (flags & ARGP_HELP_POST_DOC) /* Print any documentation strings at the end. */ anything |= argp_doc (argp, state, 1, anything, 0, fs); if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address) { if (anything) __argp_fmtstream_putc (fs, '\n'); __argp_fmtstream_printf (fs, _("Report bugs to %s.\n"), argp_program_bug_address); anything = 1; } if (hol) hol_free (hol); __argp_fmtstream_free (fs);}/* Output a usage message for ARGP to STREAM. FLAGS are from the set ARGP_HELP_*. NAME is what to use wherever a `program name' is needed. */void __argp_help (const struct argp *argp, FILE *stream, unsigned flags, char *name){ _help (argp, 0, stream, flags, name);}#ifdef weak_aliasweak_alias (__argp_help, argp_help)#endif/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are from the set ARGP_HELP_*. */void__argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags){ if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream) { if (state && (state->flags & ARGP_LONG_ONLY)) flags |= ARGP_HELP_LONG_ONLY; _help (state ? state->argp : 0, state, stream, flags, state ? state->name : program_invocation_short_name); if (!state || ! (state->flags & ARGP_NO_EXIT)) { if (flags & ARGP_HELP_EXIT_ERR) exit (1); if (flags & ARGP_HELP_EXIT_OK) exit (0); } }}#ifdef weak_aliasweak_alias (__argp_state_help, argp_state_help)#endif/* If appropriate, print the printf string FMT and following args, preceded by the program name and `:', to stderr, and followed by a `Try ... --help' message, then exit (1). */void__argp_error (const struct argp_state *state, const char *fmt, ...){ if (!state || !(state->flags & ARGP_NO_ERRS)) { FILE *stream = state ? state->err_stream : stderr; if (stream) { va_list ap; fputs (state ? state->name : program_invocation_short_name, stream); putc (':', stream); putc (' ', stream); va_start (ap, fmt); vfprintf (stream, fmt, ap); va_end (ap); putc ('\n', stream); __argp_state_help (state, stream, ARGP_HELP_STD_ERR); } }}#ifdef weak_aliasweak_alias (__argp_error, argp_error)#endif/* Similar to the standard gnu error-reporting function error(), but will respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print to STATE->err_stream. This is useful for argument parsing code that is shared between program startup (when exiting is desired) and runtime option parsing (when typically an error code is returned instead). The difference between this function and argp_error is that the latter is for *parsing errors*, and the former is for other problems that occur during parsing but don't reflect a (syntactic) problem with the input. */void__argp_failure (const struct argp_state *state, int status, int errnum, const char *fmt, ...){ if (!state || !(state->flags & ARGP_NO_ERRS)) { FILE *stream = state ? state->err_stream : stderr; if (stream) { fputs (state ? state->name : program_invocation_short_name, stream); if (fmt) { va_list ap; putc (':', stream); putc (' ', stream); va_start (ap, fmt); vfprintf (stream, fmt, ap); va_end (ap); } if (errnum) { putc (':', stream); putc (' ', stream);#if HAVE_STRERROR fputs (strerror (errnum), stream);#else fprintf (stream, "error %d\n", errnum);#endif } putc ('\n', stream); if (status && (!state || !(state->flags & ARGP_NO_EXIT))) exit (status); } }}#ifdef weak_aliasweak_alias (__argp_failure, argp_failure)#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -