1 /* Hierarchical argument parsing help output 2 Copyright (C) 1995-2021 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 Written by Miles Bader <miles@gnu.ai.mit.edu>. 5 6 This file is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as 8 published by the Free Software Foundation; either version 3 of the 9 License, or (at your option) any later version. 10 11 This file is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of signal_(int * signum,sighandler_t handler)13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public License 17 along with this program. If not, see <https://www.gnu.org/licenses/>. */ 18 19 #ifndef _GNU_SOURCE 20 # define _GNU_SOURCE 1 21 #endif 22 23 #ifdef HAVE_CONFIG_H 24 # include <config.h> 25 #endif 26 27 #include <alloca.h> 28 #include <errno.h> 29 #include <stdbool.h> 30 #include <stddef.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <strings.h> 34 #include <assert.h> 35 #include <stdarg.h> 36 #include <ctype.h> 37 #include <limits.h> 38 #ifdef _LIBC 39 # include <../libio/libioP.h> 40 # include <wchar.h> 41 #endif 42 43 #ifdef _LIBC 44 # include <libintl.h> 45 # undef dgettext 46 # define dgettext(domain, msgid) \ 47 __dcgettext (domain, msgid, LC_MESSAGES) 48 #else 49 # include "gettext.h" 50 #endif 51 52 #include "argp.h" 53 #include "argp-fmtstream.h" 54 #include "argp-namefrob.h" 55 56 #ifndef SIZE_MAX 57 # define SIZE_MAX ((size_t) -1) 58 #endif 59 60 /* ========================================================================== */ 61 62 /* User-selectable (using an environment variable) formatting parameters. 63 64 These may be specified in an environment variable called 'ARGP_HELP_FMT', 65 with a contents like: VAR1=VAL1,VAR2=VAL2,BOOLVAR2,no-BOOLVAR2 66 Where VALn must be a positive integer. The list of variables is in the 67 UPARAM_NAMES vector, below. */ 68 69 /* Default parameters. */ 70 #define DUP_ARGS 0 /* True if option argument can be duplicated. */ 71 #define DUP_ARGS_NOTE 1 /* True to print a note about duplicate args. */ 72 #define SHORT_OPT_COL 2 /* column in which short options start */ 73 #define LONG_OPT_COL 6 /* column in which long options start */ 74 #define DOC_OPT_COL 2 /* column in which doc options start */ 75 #define OPT_DOC_COL 29 /* column in which option text starts */ 76 #define HEADER_COL 1 /* column in which group headers are printed */ 77 #define USAGE_INDENT 12 /* indentation of wrapped usage lines */ 78 #define RMARGIN 79 /* right margin used for wrapping */ 79 80 /* User-selectable (using an environment variable) formatting parameters. 81 They must all be of type 'int' for the parsing code to work. */ 82 struct uparams 83 { 84 /* If true, arguments for an option are shown with both short and long 85 options, even when a given option has both, e.g. '-x ARG, --longx=ARG'. 86 If false, then if an option has both, the argument is only shown with 87 the long one, e.g., '-x, --longx=ARG', and a message indicating that 88 this really means both is printed below the options. */ 89 int dup_args; 90 91 /* This is true if when DUP_ARGS is false, and some duplicate arguments have 92 been suppressed, an explanatory message should be printed. */ 93 int dup_args_note; 94 95 /* Various output columns. */ 96 int short_opt_col; /* column in which short options start */ 97 int long_opt_col; /* column in which long options start */ 98 int doc_opt_col; /* column in which doc options start */ 99 int opt_doc_col; /* column in which option text starts */ 100 int header_col; /* column in which group headers are printed */ 101 int usage_indent; /* indentation of wrapped usage lines */ 102 int rmargin; /* right margin used for wrapping */ 103 104 int valid; /* True when the values in here are valid. */ 105 }; 106 107 /* This is a global variable, as user options are only ever read once. */ 108 static struct uparams uparams = { 109 DUP_ARGS, DUP_ARGS_NOTE, 110 SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL, 111 USAGE_INDENT, RMARGIN 112 }; 113 114 /* A particular uparam, and what the user name is. */ 115 struct uparam_name 116 { 117 const char name[14]; /* User name. */ 118 bool is_bool; /* Whether it's 'boolean'. */ 119 unsigned char uparams_offs; /* Location of the (int) field in UPARAMS. */ 120 }; 121 122 /* The name-field mappings we know about. */ 123 static const struct uparam_name uparam_names[] = 124 { 125 { "dup-args", true, offsetof (struct uparams, dup_args) }, 126 { "dup-args-note", true, offsetof (struct uparams, dup_args_note) }, 127 { "short-opt-col", false, offsetof (struct uparams, short_opt_col) }, 128 { "long-opt-col", false, offsetof (struct uparams, long_opt_col) }, 129 { "doc-opt-col", false, offsetof (struct uparams, doc_opt_col) }, 130 { "opt-doc-col", false, offsetof (struct uparams, opt_doc_col) }, 131 { "header-col", false, offsetof (struct uparams, header_col) }, 132 { "usage-indent", false, offsetof (struct uparams, usage_indent) }, 133 { "rmargin", false, offsetof (struct uparams, rmargin) } 134 }; 135 #define nuparam_names (sizeof (uparam_names) / sizeof (uparam_names[0])) 136 137 static void 138 validate_uparams (const struct argp_state *state, struct uparams *upptr) 139 { 140 const struct uparam_name *up; 141 142 for (up = uparam_names; up < uparam_names + nuparam_names; up++) 143 { 144 if (up->is_bool 145 || up->uparams_offs == offsetof (struct uparams, rmargin)) 146 continue; 147 if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin) 148 { 149 __argp_failure (state, 0, 0, 150 dgettext (state == NULL ? NULL 151 : state->root_argp->argp_domain, 152 "\ 153 ARGP_HELP_FMT: %s value is less than or equal to %s"), 154 "rmargin", up->name); 155 return; 156 } 157 } 158 uparams = *upptr; 159 uparams.valid = 1; 160 } 161 162 /* Read user options from the environment, and fill in UPARAMS appropriately. */ 163 static void 164 fill_in_uparams (const struct argp_state *state) 165 { 166 const char *var = getenv ("ARGP_HELP_FMT"); 167 struct uparams new_params = uparams; 168 169 #define SKIPWS(p) do { while (isspace ((unsigned char) *p)) p++; } while (0); 170 171 if (var) 172 { 173 /* Parse var. */ 174 while (*var) 175 { 176 SKIPWS (var); 177 178 if (isalpha ((unsigned char) *var)) 179 { 180 size_t var_len; 181 const struct uparam_name *un; 182 int unspec = 0, val = 0; 183 const char *arg = var; 184 185 while (isalnum ((unsigned char) *arg) || *arg == '-' || *arg == '_') 186 arg++; 187 var_len = arg - var; 188 189 SKIPWS (arg); 190 191 if (*arg == '\0' || *arg == ',') 192 unspec = 1; 193 else if (*arg == '=') 194 { 195 arg++; 196 SKIPWS (arg); 197 } 198 199 if (unspec) 200 { 201 if (var[0] == 'n' && var[1] == 'o' && var[2] == '-') 202 { 203 val = 0; 204 var += 3; 205 var_len -= 3; 206 } 207 else 208 val = 1; 209 } 210 else if (isdigit ((unsigned char) *arg)) 211 { 212 val = atoi (arg); 213 while (isdigit ((unsigned char) *arg)) 214 arg++; 215 SKIPWS (arg); 216 } 217 218 for (un = uparam_names; 219 un < uparam_names + nuparam_names; 220 un++) 221 if (strlen (un->name) == var_len 222 && strncmp (var, un->name, var_len) == 0) 223 { 224 if (unspec && !un->is_bool) 225 __argp_failure (state, 0, 0, 226 dgettext (state == NULL ? NULL 227 : state->root_argp->argp_domain, 228 "\ 229 %.*s: ARGP_HELP_FMT parameter requires a value"), 230 (int) var_len, var); 231 else 232 *(int *)((char *)&new_params + un->uparams_offs) = val; 233 break; 234 } 235 if (un == uparam_names + nuparam_names) 236 __argp_failure (state, 0, 0, 237 dgettext (state == NULL ? NULL 238 : state->root_argp->argp_domain, "\ 239 %.*s: Unknown ARGP_HELP_FMT parameter"), 240 (int) var_len, var); 241 242 var = arg; 243 if (*var == ',') 244 var++; 245 } 246 else if (*var) 247 { 248 __argp_failure (state, 0, 0, 249 dgettext (state == NULL ? NULL 250 : state->root_argp->argp_domain, 251 "Garbage in ARGP_HELP_FMT: %s"), var); 252 break; 253 } 254 } 255 validate_uparams (state, &new_params); 256 } 257 } 258 259 /* ========================================================================== */ 260 261 /* Returns true if OPT hasn't been marked invisible. Visibility only affects 262 whether OPT is displayed or used in sorting, not option shadowing. */ 263 #define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN)) 264 265 /* Returns true if OPT is an alias for an earlier option. */ 266 #define oalias(opt) ((opt)->flags & OPTION_ALIAS) 267 268 /* Returns true if OPT is a documentation-only entry. */ 269 #define odoc(opt) ((opt)->flags & OPTION_DOC) 270 271 /* Returns true if OPT should not be translated */ 272 #define onotrans(opt) ((opt)->flags & OPTION_NO_TRANS) 273 274 /* Returns true if OPT is the end-of-list marker for a list of options. */ 275 #define oend(opt) __option_is_end (opt) 276 277 /* Returns true if OPT has a short option. */ 278 #define oshort(opt) __option_is_short (opt) 279 280 /* 281 The help format for a particular option is like: 282 283 -xARG, -yARG, --long1=ARG, --long2=ARG Documentation... 284 285 Where ARG will be omitted if there's no argument, for this option, or 286 will be surrounded by "[" and "]" appropriately if the argument is 287 optional. The documentation string is word-wrapped appropriately, and if 288 the list of options is long enough, it will be started on a separate line. 289 If there are no short options for a given option, the first long option is 290 indented slightly in a way that's supposed to make most long options appear 291 to be in a separate column. 292 293 For example, the following output (from ps): 294 295 -p PID, --pid=PID List the process PID 296 --pgrp=PGRP List processes in the process group PGRP 297 -P, -x, --no-parent Include processes without parents 298 -Q, --all-fields Don't elide unusable fields (normally if there's 299 some reason ps can't print a field for any 300 process, it's removed from the output entirely) 301 -r, --reverse, --gratuitously-long-reverse-option 302 Reverse the order of any sort 303 --session[=SID] Add the processes from the session SID (which 304 defaults to the sid of the current process) 305 306 Here are some more options: 307 -f ZOT, --foonly=ZOT Glork a foonly 308 -z, --zaza Snit a zar 309 310 -?, --help Give this help list 311 --usage Give a short usage message 312 -V, --version Print program version 313 314 The struct argp_option array for the above could look like: 315 316 { 317 {"pid", 'p', "PID", 0, "List the process PID"}, 318 {"pgrp", OPT_PGRP, "PGRP", 0, "List processes in the process group PGRP"}, 319 {"no-parent", 'P', 0, 0, "Include processes without parents"}, 320 {0, 'x', 0, OPTION_ALIAS}, 321 {"all-fields",'Q', 0, 0, "Don't elide unusable fields (normally" 322 " if there's some reason ps can't" 323 " print a field for any process, it's" 324 " removed from the output entirely)" }, 325 {"reverse", 'r', 0, 0, "Reverse the order of any sort"}, 326 {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS}, 327 {"session", OPT_SESS, "SID", OPTION_ARG_OPTIONAL, 328 "Add the processes from the session" 329 " SID (which defaults to the sid of" 330 " the current process)" }, 331 332 {0,0,0,0, "Here are some more options:"}, 333 {"foonly", 'f', "ZOT", 0, "Glork a foonly"}, 334 {"zaza", 'z', 0, 0, "Snit a zar"}, 335 336 {0} 337 } 338 339 Note that the last three options are automatically supplied by argp_parse, 340 unless you tell it not to with ARGP_NO_HELP. 341 342 */ 343 344 /* Returns true if CH occurs between BEG and END. */ 345 static int 346 find_char (char ch, char *beg, char *end) 347 { 348 while (beg < end) 349 if (*beg == ch) 350 return 1; 351 else 352 beg++; 353 return 0; 354 } 355 356 /* -------------------------------------------------------------------------- */ 357 /* Data structure: HOL = Help Option List */ 358 359 struct hol_cluster; /* fwd decl */ 360 361 struct hol_entry 362 { 363 /* First option. */ 364 const struct argp_option *opt; 365 /* Number of options (including aliases). */ 366 unsigned num; 367 368 /* A pointers into the HOL's short_options field, to the first short option 369 letter for this entry. The order of the characters following this point 370 corresponds to the order of options pointed to by OPT, and there are at 371 most NUM. A short option recorded in an option following OPT is only 372 valid if it occurs in the right place in SHORT_OPTIONS (otherwise it's 373 probably been shadowed by some other entry). */ 374 char *short_options; 375 376 /* Entries are sorted by their group first, in the order: 377 0, 1, 2, ..., n, -m, ..., -2, -1 378 and then alphabetically within each group. The default is 0. */ 379 int group; 380 381 /* The cluster of options this entry belongs to, or NULL if none. */ 382 struct hol_cluster *cluster; 383 384 /* The argp from which this option came. */ 385 const struct argp *argp; 386 387 /* Position in the array */ 388 unsigned ord; 389 }; 390 391 /* A cluster of entries to reflect the argp tree structure. */ 392 struct hol_cluster 393 { 394 /* A descriptive header printed before options in this cluster. */ 395 const char *header; 396 397 /* Used to order clusters within the same group with the same parent, 398 according to the order in which they occurred in the parent argp's child 399 list. */ 400 int index; 401 402 /* How to sort this cluster with respect to options and other clusters at the 403 same depth (clusters always follow options in the same group). */ 404 int group; 405 406 /* The cluster to which this cluster belongs, or NULL if it's at the base 407 level. */ 408 struct hol_cluster *parent; 409 410 /* The argp from which this cluster is (eventually) derived. */ 411 const struct argp *argp; 412 413 /* The distance this cluster is from the root. */ 414 int depth; 415 416 /* Clusters in a given hol are kept in a linked list, to make freeing them 417 possible. */ 418 struct hol_cluster *next; 419 }; 420 421 /* A list of options for help. */ 422 struct hol 423 { 424 /* An array of hol_entry's. */ 425 struct hol_entry *entries; 426 /* The number of entries in this hol. If this field is zero, the others 427 are undefined. */ 428 unsigned num_entries; 429 430 /* A string containing all short options in this HOL. Each entry contains 431 pointers into this string, so the order can't be messed with blindly. */ 432 char *short_options; 433 434 /* Clusters of entries in this hol. */ 435 struct hol_cluster *clusters; 436 }; 437 438 /* Create a struct hol from the options in ARGP. CLUSTER is the 439 hol_cluster in which these entries occur, or NULL if at the root. */ 440 static struct hol * 441 make_hol (const struct argp *argp, struct hol_cluster *cluster) 442 { 443 char *so; 444 const struct argp_option *o; 445 const struct argp_option *opts = argp->options; 446 struct hol_entry *entry; 447 unsigned num_short_options = 0; 448 struct hol *hol = malloc (sizeof (struct hol)); 449 450 assert (hol); 451 452 hol->num_entries = 0; 453 hol->clusters = 0; 454 455 if (opts) 456 { 457 int cur_group = 0; 458 459 /* The first option must not be an alias. */ 460 assert (! oalias (opts)); 461 462 /* Calculate the space needed. */ 463 for (o = opts; ! oend (o); o++) 464 { 465 if (! oalias (o)) 466 hol->num_entries++; 467 if (oshort (o)) 468 num_short_options++; /* This is an upper bound. */ 469 } 470 471 hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries); 472 hol->short_options = malloc (num_short_options + 1); 473 474 assert (hol->entries && hol->short_options); 475 if (SIZE_MAX <= UINT_MAX) 476 assert (hol->num_entries <= SIZE_MAX / sizeof (struct hol_entry)); 477 478 /* Fill in the entries. */ 479 so = hol->short_options; 480 for (o = opts, entry = hol->entries; ! oend (o); entry++) 481 { 482 entry->opt = o; 483 entry->num = 0; 484 entry->short_options = so; 485 entry->group = cur_group = 486 o->group 487 ? o->group 488 : ((!o->name && !o->key) 489 ? cur_group + 1 490 : cur_group); 491 entry->cluster = cluster; 492 entry->argp = argp; 493 494 do 495 { 496 entry->num++; 497 if (oshort (o) && ! find_char (o->key, hol->short_options, so)) 498 /* O has a valid short option which hasn't already been used.*/ 499 *so++ = o->key; 500 o++; 501 } 502 while (! oend (o) && oalias (o)); 503 } 504 *so = '\0'; /* null terminated so we can find the length */ 505 } 506 507 return hol; 508 } 509 510 /* Add a new cluster to HOL, with the given GROUP and HEADER (taken from the 511 associated argp child list entry), INDEX, and PARENT, and return a pointer 512 to it. ARGP is the argp that this cluster results from. */ 513 static struct hol_cluster * 514 hol_add_cluster (struct hol *hol, int group, const char *header, int index, 515 struct hol_cluster *parent, const struct argp *argp) 516 { 517 struct hol_cluster *cl = malloc (sizeof (struct hol_cluster)); 518 if (cl) 519 { 520 cl->group = group; 521 cl->header = header; 522 523 cl->index = index; 524 cl->parent = parent; 525 cl->argp = argp; 526 cl->depth = parent ? parent->depth + 1 : 0; 527 528 cl->next = hol->clusters; 529 hol->clusters = cl; 530 } 531 return cl; 532 } 533 534 /* Free HOL and any resources it uses. */ 535 static void 536 hol_free (struct hol *hol) 537 { 538 struct hol_cluster *cl = hol->clusters; 539 540 while (cl) 541 { 542 struct hol_cluster *next = cl->next; 543 free (cl); 544 cl = next; 545 } 546 547 if (hol->num_entries > 0) 548 { 549 free (hol->entries); 550 free (hol->short_options); 551 } 552 553 free (hol); 554 } 555 556 /* Iterate across the short_options of the given ENTRY. Call FUNC for each. 557 Stop when such a call returns a non-zero value, and return this value. 558 If all FUNC invocations returned 0, return 0. */ 559 static int 560 hol_entry_short_iterate (const struct hol_entry *entry, 561 int (*func)(const struct argp_option *opt, 562 const struct argp_option *real, 563 const char *domain, void *cookie), 564 const char *domain, void *cookie) 565 { 566 unsigned nopts; 567 int val = 0; 568 const struct argp_option *opt, *real = entry->opt; 569 char *so = entry->short_options; 570 571 for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) 572 if (oshort (opt) && *so == opt->key) 573 { 574 if (!oalias (opt)) 575 real = opt; 576 if (ovisible (opt)) 577 val = (*func)(opt, real, domain, cookie); 578 so++; 579 } 580 581 return val; 582 } 583 584 /* Iterate across the long options of the given ENTRY. Call FUNC for each. 585 Stop when such a call returns a non-zero value, and return this value. 586 If all FUNC invocations returned 0, return 0. */ 587 static inline int 588 #if (__GNUC__ >= 3) || (__clang_major__ >= 4) 589 __attribute__ ((always_inline)) 590 #endif 591 hol_entry_long_iterate (const struct hol_entry *entry, 592 int (*func)(const struct argp_option *opt, 593 const struct argp_option *real, 594 const char *domain, void *cookie), 595 const char *domain, void *cookie) 596 { 597 unsigned nopts; 598 int val = 0; 599 const struct argp_option *opt, *real = entry->opt; 600 601 for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) 602 if (opt->name) 603 { 604 if (!oalias (opt)) 605 real = opt; 606 if (ovisible (opt)) 607 val = (*func)(opt, real, domain, cookie); 608 } 609 610 return val; 611 } 612 613 /* A filter that returns true for the first short option of a given ENTRY. */ 614 static int 615 until_short (const struct argp_option *opt, const struct argp_option *real, 616 const char *domain, void *cookie) 617 { 618 return oshort (opt) ? opt->key : 0; 619 } 620 621 /* Returns the first valid short option in ENTRY, or 0 if there is none. */ 622 static char 623 hol_entry_first_short (const struct hol_entry *entry) 624 { 625 return hol_entry_short_iterate (entry, until_short, 626 entry->argp->argp_domain, 0); 627 } 628 629 /* Returns the first valid long option in ENTRY, or NULL if there is none. */ 630 static const char * 631 hol_entry_first_long (const struct hol_entry *entry) 632 { 633 const struct argp_option *opt; 634 unsigned num; 635 for (opt = entry->opt, num = entry->num; num > 0; opt++, num--) 636 if (opt->name && ovisible (opt)) 637 return opt->name; 638 return 0; 639 } 640 641 /* Returns the entry in HOL with the long option name NAME, or NULL if there is 642 none. */ 643 static struct hol_entry * 644 hol_find_entry (struct hol *hol, const char *name) 645 { 646 struct hol_entry *entry = hol->entries; 647 unsigned num_entries = hol->num_entries; 648 649 while (num_entries-- > 0) 650 { 651 const struct argp_option *opt = entry->opt; 652 unsigned num_opts = entry->num; 653 654 while (num_opts-- > 0) 655 if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0) 656 return entry; 657 else 658 opt++; 659 660 entry++; 661 } 662 663 return 0; 664 } 665 666 /* If an entry with the long option NAME occurs in HOL, set its special 667 sort position to GROUP. */ 668 static void 669 hol_set_group (struct hol *hol, const char *name, int group) 670 { 671 struct hol_entry *entry = hol_find_entry (hol, name); 672 if (entry) 673 entry->group = group; 674 } 675 676 /* -------------------------------------------------------------------------- */ 677 /* Sorting the entries in a HOL. */ 678 679 /* Order by group: 0, 1, 2, ..., n, -m, ..., -2, -1. */ 680 static int 681 group_cmp (int group1, int group2) 682 { 683 if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0)) 684 return group1 - group2; 685 else 686 /* Return > 0 if group1 < 0 <= group2. 687 Return < 0 if group2 < 0 <= group1. */ 688 return group2 - group1; 689 } 690 691 /* Compare clusters CL1 and CL2 by the order that they should appear in 692 output. Assume CL1 and CL2 have the same parent. */ 693 static int 694 hol_sibling_cluster_cmp (const struct hol_cluster *cl1, 695 const struct hol_cluster *cl2) 696 { 697 /* Compare by group first. */ 698 int cmp = group_cmp (cl1->group, cl2->group); 699 if (cmp != 0) 700 return cmp; 701 702 /* Within a group, compare by index within the group. */ 703 return cl2->index - cl1->index; 704 } 705 706 /* Compare clusters CL1 and CL2 by the order that they should appear in 707 output. Assume CL1 and CL2 are at the same depth. */ 708 static int 709 hol_cousin_cluster_cmp (const struct hol_cluster *cl1, 710 const struct hol_cluster *cl2) 711 { 712 if (cl1->parent == cl2->parent) 713 return hol_sibling_cluster_cmp (cl1, cl2); 714 else 715 { 716 /* Compare the parent clusters first. */ 717 int cmp = hol_cousin_cluster_cmp (cl1->parent, cl2->parent); 718 if (cmp != 0) 719 return cmp; 720 721 /* Next, compare by group. */ 722 cmp = group_cmp (cl1->group, cl2->group); 723 if (cmp != 0) 724 return cmp; 725 726 /* Next, within a group, compare by index within the group. */ 727 return cl2->index - cl1->index; 728 } 729 } 730 731 /* Compare clusters CL1 and CL2 by the order that they should appear in 732 output. */ 733 static int 734 hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2) 735 { 736 /* If one cluster is deeper than the other, use its ancestor at the same 737 level. Then, go by the rule that entries that are not in a sub-cluster 738 come before entries in a sub-cluster. */ 739 if (cl1->depth > cl2->depth) 740 { 741 do 742 cl1 = cl1->parent; 743 while (cl1->depth > cl2->depth); 744 int cmp = hol_cousin_cluster_cmp (cl1, cl2); 745 if (cmp != 0) 746 return cmp; 747 748 return 1; 749 } 750 else if (cl1->depth < cl2->depth) 751 { 752 do 753 cl2 = cl2->parent; 754 while (cl1->depth < cl2->depth); 755 int cmp = hol_cousin_cluster_cmp (cl1, cl2); 756 if (cmp != 0) 757 return cmp; 758 759 return -1; 760 } 761 else 762 return hol_cousin_cluster_cmp (cl1, cl2); 763 } 764 765 /* Return the ancestor of CL that's just below the root (i.e., has a parent 766 of 0). */ 767 static struct hol_cluster * 768 hol_cluster_base (struct hol_cluster *cl) 769 { 770 while (cl->parent) 771 cl = cl->parent; 772 return cl; 773 } 774 775 /* Given the name of an OPTION_DOC option, modifies *NAME to start at the tail 776 that should be used for comparisons, and returns true iff it should be 777 treated as a non-option. */ 778 static int 779 canon_doc_option (const char **name) 780 { 781 int non_opt; 782 /* Skip initial whitespace. */ 783 while (isspace ((unsigned char) **name)) 784 (*name)++; 785 /* Decide whether this looks like an option (leading '-') or not. */ 786 non_opt = (**name != '-'); 787 /* Skip until part of name used for sorting. */ 788 while (**name && !isalnum ((unsigned char) **name)) 789 (*name)++; 790 return non_opt; 791 } 792 793 /* Order ENTRY1 and ENTRY2 by the order which they should appear in a help 794 listing. 795 This function implements a total order, that is: 796 - if cmp (entry1, entry2) < 0 and cmp (entry2, entry3) < 0, 797 then cmp (entry1, entry3) < 0. 798 - if cmp (entry1, entry2) < 0 and cmp (entry2, entry3) == 0, 799 then cmp (entry1, entry3) < 0. 800 - if cmp (entry1, entry2) == 0 and cmp (entry2, entry3) < 0, 801 then cmp (entry1, entry3) < 0. 802 - if cmp (entry1, entry2) == 0 and cmp (entry2, entry3) == 0, 803 then cmp (entry1, entry3) == 0. */ 804 static int 805 hol_entry_cmp (const struct hol_entry *entry1, 806 const struct hol_entry *entry2) 807 { 808 /* First, compare the group numbers. For entries within a cluster, what 809 matters is the group number of the base cluster in which the entry 810 resides. */ 811 int group1 = (entry1->cluster 812 ? hol_cluster_base (entry1->cluster)->group 813 : entry1->group); 814 int group2 = (entry2->cluster 815 ? hol_cluster_base (entry2->cluster)->group 816 : entry2->group); 817 int cmp = group_cmp (group1, group2); 818 if (cmp != 0) 819 return cmp; 820 821 /* The group numbers are the same. */ 822 823 /* Entries that are not in a cluster come before entries in a cluster. */ 824 cmp = (entry1->cluster != NULL) - (entry2->cluster != NULL); 825 if (cmp != 0) 826 return cmp; 827 828 /* Compare the clusters. */ 829 if (entry1->cluster != NULL) 830 { 831 cmp = hol_cluster_cmp (entry1->cluster, entry2->cluster); 832 if (cmp != 0) 833 return cmp; 834 } 835 836 /* For entries in the same cluster, compare also the group numbers 837 within the cluster. */ 838 cmp = group_cmp (entry1->group, entry2->group); 839 if (cmp != 0) 840 return cmp; 841 842 /* The entries are both in the same group and the same cluster. */ 843 844 /* 'documentation' options always follow normal options (or documentation 845 options that *look* like normal options). */ 846 const char *long1 = hol_entry_first_long (entry1); 847 const char *long2 = hol_entry_first_long (entry2); 848 int doc1 = 849 (odoc (entry1->opt) ? long1 != NULL && canon_doc_option (&long1) : 0); 850 int doc2 = 851 (odoc (entry2->opt) ? long2 != NULL && canon_doc_option (&long2) : 0); 852 cmp = doc1 - doc2; 853 if (cmp != 0) 854 return cmp; 855 856 /* Compare the entries alphabetically. */ 857 858 /* First, compare the first character of the options. 859 Put entries without *any* valid options (such as options with 860 OPTION_HIDDEN set) first. But as they're not displayed, it doesn't 861 matter where they are. */ 862 int short1 = hol_entry_first_short (entry1); 863 int short2 = hol_entry_first_short (entry2); 864 unsigned char first1 = short1 ? short1 : long1 != NULL ? *long1 : 0; 865 unsigned char first2 = short2 ? short2 : long2 != NULL ? *long2 : 0; 866 /* Compare ignoring case. */ 867 /* Use tolower, not _tolower, since the latter has undefined behaviour 868 for characters that are not uppercase letters. */ 869 cmp = tolower (first1) - tolower (first2); 870 if (cmp != 0) 871 return cmp; 872 /* When the options start with the same letter (ignoring case), lower-case 873 comes first. */ 874 cmp = first2 - first1; 875 if (cmp != 0) 876 return cmp; 877 878 /* The first character of the options agree. */ 879 880 /* Put entries with a short option before entries without a short option. */ 881 cmp = (short1 != 0) - (short2 != 0); 882 if (cmp != 0) 883 return cmp; 884 885 /* Compare entries without a short option by comparing the long option. */ 886 if (short1 == 0) 887 { 888 cmp = (long1 != NULL) - (long2 != NULL); 889 if (cmp != 0) 890 return cmp; 891 892 if (long1 != NULL) 893 { 894 cmp = __strcasecmp (long1, long2); 895 if (cmp != 0) 896 return cmp; 897 } 898 } 899 900 /* We're out of comparison criteria. At this point, if ENTRY1 != ENTRY2, 901 the order of these entries will be unpredictable. */ 902 return 0; 903 } 904 905 /* Variant of hol_entry_cmp with correct signature for qsort. */ 906 static int 907 hol_entry_qcmp (const void *entry1_v, const void *entry2_v) 908 { 909 return hol_entry_cmp (entry1_v, entry2_v); 910 } 911 912 /* Sort HOL by group and alphabetically by option name (with short options 913 taking precedence over long). Since the sorting is for display purposes 914 only, the shadowing of options isn't effected. */ 915 static void 916 hol_sort (struct hol *hol) 917 { 918 if (hol->num_entries > 0) 919 { 920 unsigned i; 921 struct hol_entry *e; 922 for (i = 0, e = hol->entries; i < hol->num_entries; i++, e++) 923 e->ord = i; 924 925 qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry), 926 hol_entry_qcmp); 927 } 928 } 929 930 /* -------------------------------------------------------------------------- */ 931 /* Constructing the HOL. */ 932 933 /* Append MORE to HOL, destroying MORE in the process. Options in HOL shadow 934 any in MORE with the same name. */ 935 static void 936 hol_append (struct hol *hol, struct hol *more) 937 { 938 struct hol_cluster **cl_end = &hol->clusters; 939 940 /* Steal MORE's cluster list, and add it to the end of HOL's. */ 941 while (*cl_end) 942 cl_end = &(*cl_end)->next; 943 *cl_end = more->clusters; 944 more->clusters = 0; 945 946 /* Merge entries. */ 947 if (more->num_entries > 0) 948 { 949 if (hol->num_entries == 0) 950 { 951 hol->num_entries = more->num_entries; 952 hol->entries = more->entries; 953 hol->short_options = more->short_options; 954 more->num_entries = 0; /* Mark MORE's fields as invalid. */ 955 } 956 else 957 /* Append the entries in MORE to those in HOL, taking care to only add 958 non-shadowed SHORT_OPTIONS values. */ 959 { 960 unsigned left; 961 char *so, *more_so; 962 struct hol_entry *e; 963 unsigned num_entries = hol->num_entries + more->num_entries; 964 struct hol_entry *entries = 965 malloc (num_entries * sizeof (struct hol_entry)); 966 unsigned hol_so_len = strlen (hol->short_options); 967 char *short_options = 968 malloc (hol_so_len + strlen (more->short_options) + 1); 969 970 assert (entries && short_options); 971 if (SIZE_MAX <= UINT_MAX) 972 assert (num_entries <= SIZE_MAX / sizeof (struct hol_entry)); 973 974 __mempcpy (__mempcpy (entries, hol->entries, 975 hol->num_entries * sizeof (struct hol_entry)), 976 more->entries, 977 more->num_entries * sizeof (struct hol_entry)); 978 979 __mempcpy (short_options, hol->short_options, hol_so_len); 980 981 /* Fix up the short options pointers from HOL. */ 982 for (e = entries, left = hol->num_entries; left > 0; e++, left--) 983 e->short_options 984 = short_options + (e->short_options - hol->short_options); 985 986 /* Now add the short options from MORE, fixing up its entries 987 too. */ 988 so = short_options + hol_so_len; 989 more_so = more->short_options; 990 for (left = more->num_entries; left > 0; e++, left--) 991 { 992 int opts_left; 993 const struct argp_option *opt; 994 995 e->short_options = so; 996 997 for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--) 998 { 999 int ch = *more_so; 1000 if (oshort (opt) && ch == opt->key) 1001 /* The next short option in MORE_SO, CH, is from OPT. */ 1002 { 1003 if (! find_char (ch, short_options, 1004 short_options + hol_so_len)) 1005 /* The short option CH isn't shadowed by HOL's options, 1006 so add it to the sum. */ 1007 *so++ = ch; 1008 more_so++; 1009 } 1010 } 1011 } 1012 1013 *so = '\0'; 1014 1015 free (hol->entries); 1016 free (hol->short_options); 1017 1018 hol->entries = entries; 1019 hol->num_entries = num_entries; 1020 hol->short_options = short_options; 1021 } 1022 } 1023 1024 hol_free (more); 1025 } 1026 1027 /* Make a HOL containing all levels of options in ARGP. CLUSTER is the 1028 cluster in which ARGP's entries should be clustered, or NULL. */ 1029 static struct hol * 1030 argp_hol (const struct argp *argp, struct hol_cluster *cluster) 1031 { 1032 const struct argp_child *child = argp->children; 1033 struct hol *hol = make_hol (argp, cluster); 1034 if (child) 1035 while (child->argp) 1036 { 1037 struct hol_cluster *child_cluster = 1038 ((child->group || child->header) 1039 /* Put CHILD->argp within its own cluster. */ 1040 ? hol_add_cluster (hol, child->group, child->header, 1041 child - argp->children, cluster, argp) 1042 /* Just merge it into the parent's cluster. */ 1043 : cluster); 1044 hol_append (hol, argp_hol (child->argp, child_cluster)) ; 1045 child++; 1046 } 1047 return hol; 1048 } 1049 1050 /* -------------------------------------------------------------------------- */ 1051 /* Printing the HOL. */ 1052 1053 /* Inserts enough spaces to make sure STREAM is at column COL. */ 1054 static void 1055 indent_to (argp_fmtstream_t stream, unsigned col) 1056 { 1057 int needed = col - __argp_fmtstream_point (stream); 1058 while (needed-- > 0) 1059 __argp_fmtstream_putc (stream, ' '); 1060 } 1061 1062 /* Output to STREAM either a space, or a newline if there isn't room for at 1063 least ENSURE characters before the right margin. */ 1064 static void 1065 space (argp_fmtstream_t stream, size_t ensure) 1066 { 1067 if (__argp_fmtstream_point (stream) + ensure 1068 >= __argp_fmtstream_rmargin (stream)) 1069 __argp_fmtstream_putc (stream, '\n'); 1070 else 1071 __argp_fmtstream_putc (stream, ' '); 1072 } 1073 1074 /* If the option REAL has an argument, we print it in using the printf 1075 format REQ_FMT or OPT_FMT depending on whether it's a required or 1076 optional argument. */ 1077 static void 1078 arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt, 1079 const char *domain, argp_fmtstream_t stream) 1080 { 1081 if (real->arg) 1082 { 1083 if (real->flags & OPTION_ARG_OPTIONAL) 1084 __argp_fmtstream_printf (stream, opt_fmt, 1085 dgettext (domain, real->arg)); 1086 else 1087 __argp_fmtstream_printf (stream, req_fmt, 1088 dgettext (domain, real->arg)); 1089 } 1090 } 1091 1092 /* Helper functions for hol_entry_help. */ 1093 1094 /* State used during the execution of hol_help. */ 1095 struct hol_help_state 1096 { 1097 /* PREV_ENTRY should contain the previous entry printed, or NULL. */ 1098 struct hol_entry *prev_entry; 1099 1100 /* If an entry is in a different group from the previous one, and SEP_GROUPS 1101 is true, then a blank line will be printed before any output. */ 1102 int sep_groups; 1103 1104 /* True if a duplicate option argument was suppressed (only ever set if 1105 UPARAMS.dup_args is false). */ 1106 int suppressed_dup_arg; 1107 }; 1108 1109 /* Some state used while printing a help entry (used to communicate with 1110 helper functions). See the doc for hol_entry_help for more info, as most 1111 of the fields are copied from its arguments. */ 1112 struct pentry_state 1113 { 1114 const struct hol_entry *entry; 1115 argp_fmtstream_t stream; 1116 struct hol_help_state *hhstate; 1117 1118 /* True if nothing's been printed so far. */ 1119 int first; 1120 1121 /* If non-zero, the state that was used to print this help. */ 1122 const struct argp_state *state; 1123 }; 1124 1125 /* If a user doc filter should be applied to DOC, do so. */ 1126 static const char * 1127 filter_doc (const char *doc, int key, const struct argp *argp, 1128 const struct argp_state *state) 1129 { 1130 if (argp && argp->help_filter) 1131 /* We must apply a user filter to this output. */ 1132 { 1133 void *input = __argp_input (argp, state); 1134 return (*argp->help_filter) (key, doc, input); 1135 } 1136 else 1137 /* No filter. */ 1138 return doc; 1139 } 1140 1141 /* Prints STR as a header line, with the margin lines set appropriately, and 1142 notes the fact that groups should be separated with a blank line. ARGP is 1143 the argp that should dictate any user doc filtering to take place. Note 1144 that the previous wrap margin isn't restored, but the left margin is reset 1145 to 0. */ 1146 static void 1147 print_header (const char *str, const struct argp *argp, 1148 struct pentry_state *pest) 1149 { 1150 const char *tstr = str ? dgettext (argp->argp_domain, str) : NULL; 1151 const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state); 1152 1153 if (fstr) 1154 { 1155 if (*fstr) 1156 { 1157 if (pest->hhstate->prev_entry) 1158 /* Precede with a blank line. */ 1159 __argp_fmtstream_putc (pest->stream, '\n'); 1160 indent_to (pest->stream, uparams.header_col); 1161 __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col); 1162 __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col); 1163 __argp_fmtstream_puts (pest->stream, fstr); 1164 __argp_fmtstream_set_lmargin (pest->stream, 0); 1165 __argp_fmtstream_putc (pest->stream, '\n'); 1166 } 1167 1168 pest->hhstate->sep_groups = 1; /* Separate subsequent groups. */ 1169 } 1170 1171 if (fstr != tstr) 1172 free ((char *) fstr); 1173 } 1174 1175 /* Return true if CL1 is a child of CL2. */ 1176 static int 1177 hol_cluster_is_child (const struct hol_cluster *cl1, 1178 const struct hol_cluster *cl2) 1179 { 1180 while (cl1 && cl1 != cl2) 1181 cl1 = cl1->parent; 1182 return cl1 == cl2; 1183 } 1184 1185 /* Inserts a comma if this isn't the first item on the line, and then makes 1186 sure we're at least to column COL. If this *is* the first item on a line, 1187 prints any pending whitespace/headers that should precede this line. Also 1188 clears FIRST. */ 1189 static void 1190 comma (unsigned col, struct pentry_state *pest) 1191 { 1192 if (pest->first) 1193 { 1194 const struct hol_entry *pe = pest->hhstate->prev_entry; 1195 const struct hol_cluster *cl = pest->entry->cluster; 1196 1197 if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group) 1198 __argp_fmtstream_putc (pest->stream, '\n'); 1199 1200 if (cl && cl->header && *cl->header 1201 && (!pe 1202 || (pe->cluster != cl 1203 && !hol_cluster_is_child (pe->cluster, cl)))) 1204 /* If we're changing clusters, then this must be the start of the 1205 ENTRY's cluster unless that is an ancestor of the previous one 1206 (in which case we had just popped into a sub-cluster for a bit). 1207 If so, then print the cluster's header line. */ 1208 { 1209 int old_wm = __argp_fmtstream_wmargin (pest->stream); 1210 print_header (cl->header, cl->argp, pest); 1211 __argp_fmtstream_set_wmargin (pest->stream, old_wm); 1212 } 1213 1214 pest->first = 0; 1215 } 1216 else 1217 __argp_fmtstream_puts (pest->stream, ", "); 1218 1219 indent_to (pest->stream, col); 1220 } 1221 1222 /* Print help for ENTRY to STREAM. */ 1223 static void 1224 hol_entry_help (struct hol_entry *entry, const struct argp_state *state, 1225 argp_fmtstream_t stream, struct hol_help_state *hhstate) 1226 { 1227 unsigned num; 1228 const struct argp_option *real = entry->opt, *opt; 1229 char *so = entry->short_options; 1230 int have_long_opt = 0; /* We have any long options. */ 1231 /* Saved margins. */ 1232 int old_lm = __argp_fmtstream_set_lmargin (stream, 0); 1233 int old_wm = __argp_fmtstream_wmargin (stream); 1234 /* PEST is a state block holding some of our variables that we'd like to 1235 share with helper functions. */ 1236 struct pentry_state pest = { entry, stream, hhstate, 1, state }; 1237 1238 if (! odoc (real)) 1239 for (opt = real, num = entry->num; num > 0; opt++, num--) 1240 if (opt->name && ovisible (opt)) 1241 { 1242 have_long_opt = 1; 1243 break; 1244 } 1245 1246 /* First emit short options. */ 1247 __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col); /* For truly bizarre cases. */ 1248 for (opt = real, num = entry->num; num > 0; opt++, num--) 1249 if (oshort (opt) && opt->key == *so) 1250 /* OPT has a valid (non shadowed) short option. */ 1251 { 1252 if (ovisible (opt)) 1253 { 1254 comma (uparams.short_opt_col, &pest); 1255 __argp_fmtstream_putc (stream, '-'); 1256 __argp_fmtstream_putc (stream, *so); 1257 if (!have_long_opt || uparams.dup_args) 1258 arg (real, " %s", "[%s]", 1259 state == NULL ? NULL : state->root_argp->argp_domain, 1260 stream); 1261 else if (real->arg) 1262 hhstate->suppressed_dup_arg = 1; 1263 } 1264 so++; 1265 } 1266 1267 /* Now, long options. */ 1268 if (odoc (real)) 1269 /* A "documentation" option. */ 1270 { 1271 __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col); 1272 for (opt = real, num = entry->num; num > 0; opt++, num--) 1273 if (opt->name && ovisible (opt)) 1274 { 1275 comma (uparams.doc_opt_col, &pest); 1276 /* Calling dgettext here isn't quite right, since sorting will 1277 have been done on the original; but documentation options 1278 should be pretty rare anyway... */ 1279 __argp_fmtstream_puts (stream, 1280 dgettext (state == NULL ? NULL 1281 : state->root_argp->argp_domain, 1282 opt->name)); 1283 } 1284 } 1285 else 1286 /* A real long option. */ 1287 { 1288 __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col); 1289 for (opt = real, num = entry->num; num > 0; opt++, num--) 1290 if (opt->name && ovisible (opt)) 1291 { 1292 comma (uparams.long_opt_col, &pest); 1293 __argp_fmtstream_printf (stream, "--%s", opt->name); 1294 arg (real, "=%s", "[=%s]", 1295 state == NULL ? NULL : state->root_argp->argp_domain, stream); 1296 } 1297 } 1298 1299 /* Next, documentation strings. */ 1300 __argp_fmtstream_set_lmargin (stream, 0); 1301 1302 if (pest.first) 1303 { 1304 /* Didn't print any switches, what's up? */ 1305 if (!oshort (real) && !real->name) 1306 /* This is a group header, print it nicely. */ 1307 print_header (real->doc, entry->argp, &pest); 1308 else 1309 /* Just a totally shadowed option or null header; print nothing. */ 1310 goto cleanup; /* Just return, after cleaning up. */ 1311 } 1312 else 1313 { 1314 const char *tstr = real->doc ? dgettext (state == NULL ? NULL 1315 : state->root_argp->argp_domain, 1316 real->doc) : 0; 1317 const char *fstr = filter_doc (tstr, real->key, entry->argp, state); 1318 if (fstr && *fstr) 1319 { 1320 unsigned int col = __argp_fmtstream_point (stream); 1321 1322 __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col); 1323 __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col); 1324 1325 if (col > (unsigned int) (uparams.opt_doc_col + 3)) 1326 __argp_fmtstream_putc (stream, '\n'); 1327 else if (col >= (unsigned int) uparams.opt_doc_col) 1328 __argp_fmtstream_puts (stream, " "); 1329 else 1330 indent_to (stream, uparams.opt_doc_col); 1331 1332 __argp_fmtstream_puts (stream, fstr); 1333 } 1334 if (fstr && fstr != tstr) 1335 free ((char *) fstr); 1336 1337 /* Reset the left margin. */ 1338 __argp_fmtstream_set_lmargin (stream, 0); 1339 __argp_fmtstream_putc (stream, '\n'); 1340 } 1341 1342 hhstate->prev_entry = entry; 1343 1344 cleanup: 1345 __argp_fmtstream_set_lmargin (stream, old_lm); 1346 __argp_fmtstream_set_wmargin (stream, old_wm); 1347 } 1348 1349 /* Output a long help message about the options in HOL to STREAM. */ 1350 static void 1351 hol_help (struct hol *hol, const struct argp_state *state, 1352 argp_fmtstream_t stream) 1353 { 1354 unsigned num; 1355 struct hol_entry *entry; 1356 struct hol_help_state hhstate = { 0, 0, 0 }; 1357 1358 for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--) 1359 hol_entry_help (entry, state, stream, &hhstate); 1360 1361 if (hhstate.suppressed_dup_arg && uparams.dup_args_note) 1362 { 1363 const char *tstr = dgettext (state == NULL ? NULL 1364 : state->root_argp->argp_domain, "\ 1365 Mandatory or optional arguments to long options are also mandatory or \ 1366 optional for any corresponding short options."); 1367 const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE, 1368 state ? state->root_argp : 0, state); 1369 if (fstr && *fstr) 1370 { 1371 __argp_fmtstream_putc (stream, '\n'); 1372 __argp_fmtstream_puts (stream, fstr); 1373 __argp_fmtstream_putc (stream, '\n'); 1374 } 1375 if (fstr && fstr != tstr) 1376 free ((char *) fstr); 1377 } 1378 } 1379 1380 /* Helper functions for hol_usage. */ 1381 1382 /* If OPT is a short option without an arg, append its key to the string 1383 pointer pointer to by COOKIE, and advance the pointer. */ 1384 static int 1385 add_argless_short_opt (const struct argp_option *opt, 1386 const struct argp_option *real, 1387 const char *domain, void *cookie) 1388 { 1389 char **snao_end = cookie; 1390 if (!(opt->arg || real->arg) 1391 && !((opt->flags | real->flags) & OPTION_NO_USAGE)) 1392 *(*snao_end)++ = opt->key; 1393 return 0; 1394 } 1395 1396 /* If OPT is a short option with an arg, output a usage entry for it to the 1397 stream pointed at by COOKIE. */ 1398 static int 1399 usage_argful_short_opt (const struct argp_option *opt, 1400 const struct argp_option *real, 1401 const char *domain, void *cookie) 1402 { 1403 argp_fmtstream_t stream = cookie; 1404 const char *arg = opt->arg; 1405 int flags = opt->flags | real->flags; 1406 1407 if (! arg) 1408 arg = real->arg; 1409 1410 if (arg && !(flags & OPTION_NO_USAGE)) 1411 { 1412 arg = dgettext (domain, arg); 1413 1414 if (flags & OPTION_ARG_OPTIONAL) 1415 __argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg); 1416 else 1417 { 1418 /* Manually do line wrapping so that it (probably) won't 1419 get wrapped at the embedded space. */ 1420 space (stream, 6 + strlen (arg)); 1421 __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg); 1422 } 1423 } 1424 1425 return 0; 1426 } 1427 1428 /* Output a usage entry for the long option opt to the stream pointed at by 1429 COOKIE. */ 1430 static int 1431 usage_long_opt (const struct argp_option *opt, 1432 const struct argp_option *real, 1433 const char *domain, void *cookie) 1434 { 1435 argp_fmtstream_t stream = cookie; 1436 const char *arg = opt->arg; 1437 int flags = opt->flags | real->flags; 1438 1439 if (! arg) 1440 arg = real->arg; 1441 1442 if (! (flags & OPTION_NO_USAGE)) 1443 { 1444 if (arg) 1445 { 1446 arg = dgettext (domain, arg); 1447 if (flags & OPTION_ARG_OPTIONAL) 1448 __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg); 1449 else 1450 __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg); 1451 } 1452 else 1453 __argp_fmtstream_printf (stream, " [--%s]", opt->name); 1454 } 1455 1456 return 0; 1457 } 1458 1459 /* Print a short usage description for the arguments in HOL to STREAM. */ 1460 static void 1461 hol_usage (struct hol *hol, argp_fmtstream_t stream) 1462 { 1463 if (hol->num_entries > 0) 1464 { 1465 unsigned nentries; 1466 struct hol_entry *entry; 1467 char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1); 1468 char *snao_end = short_no_arg_opts; 1469 1470 /* First we put a list of short options without arguments. */ 1471 for (entry = hol->entries, nentries = hol->num_entries 1472 ; nentries > 0 1473 ; entry++, nentries--) 1474 hol_entry_short_iterate (entry, add_argless_short_opt, 1475 entry->argp->argp_domain, &snao_end); 1476 if (snao_end > short_no_arg_opts) 1477 { 1478 *snao_end++ = 0; 1479 __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts); 1480 } 1481 1482 /* Now a list of short options *with* arguments. */ 1483 for (entry = hol->entries, nentries = hol->num_entries 1484 ; nentries > 0 1485 ; entry++, nentries--) 1486 hol_entry_short_iterate (entry, usage_argful_short_opt, 1487 entry->argp->argp_domain, stream); 1488 1489 /* Finally, a list of long options (whew!). */ 1490 for (entry = hol->entries, nentries = hol->num_entries 1491 ; nentries > 0 1492 ; entry++, nentries--) 1493 hol_entry_long_iterate (entry, usage_long_opt, 1494 entry->argp->argp_domain, stream); 1495 } 1496 } 1497 1498 /* Calculate how many different levels with alternative args strings exist in 1499 ARGP. */ 1500 static size_t 1501 argp_args_levels (const struct argp *argp) 1502 { 1503 size_t levels = 0; 1504 const struct argp_child *child = argp->children; 1505 1506 if (argp->args_doc && strchr (argp->args_doc, '\n')) 1507 levels++; 1508 1509 if (child) 1510 while (child->argp) 1511 levels += argp_args_levels ((child++)->argp); 1512 1513 return levels; 1514 } 1515 1516 /* Print all the non-option args documented in ARGP to STREAM. Any output is 1517 preceded by a space. LEVELS is a pointer to a byte vector the length 1518 returned by argp_args_levels; it should be initialized to zero, and 1519 updated by this routine for the next call if ADVANCE is true. True is 1520 returned as long as there are more patterns to output. */ 1521 static int 1522 argp_args_usage (const struct argp *argp, const struct argp_state *state, 1523 char **levels, int advance, argp_fmtstream_t stream) 1524 { 1525 char *our_level = *levels; 1526 int multiple = 0; 1527 const struct argp_child *child = argp->children; 1528 const char *tdoc = 1529 argp->args_doc ? dgettext (argp->argp_domain, argp->args_doc) : NULL; 1530 const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state); 1531 const char *nl = NULL; 1532 1533 if (fdoc) 1534 { 1535 const char *cp = fdoc; 1536 nl = __strchrnul (cp, '\n'); 1537 if (*nl != '\0') 1538 /* This is a 'multi-level' args doc; advance to the correct position 1539 as determined by our state in LEVELS, and update LEVELS. */ 1540 { 1541 int i; 1542 multiple = 1; 1543 for (i = 0; i < *our_level; i++) 1544 cp = nl + 1, nl = __strchrnul (cp, '\n'); 1545 (*levels)++; 1546 } 1547 1548 /* Manually do line wrapping so that it (probably) won't get wrapped at 1549 any embedded spaces. */ 1550 space (stream, 1 + nl - cp); 1551 1552 __argp_fmtstream_write (stream, cp, nl - cp); 1553 } 1554 if (fdoc && fdoc != tdoc) 1555 free ((char *)fdoc); /* Free user's modified doc string. */ 1556 1557 if (child) 1558 while (child->argp) 1559 advance = !argp_args_usage ((child++)->argp, state, levels, advance, stream); 1560 1561 if (advance && multiple) 1562 { 1563 /* Need to increment our level. */ 1564 if (*nl) 1565 /* There's more we can do here. */ 1566 { 1567 (*our_level)++; 1568 advance = 0; /* Our parent shouldn't advance also. */ 1569 } 1570 else if (*our_level > 0) 1571 /* We had multiple levels, but used them up; reset to zero. */ 1572 *our_level = 0; 1573 } 1574 1575 return !advance; 1576 } 1577 1578 /* Print the documentation for ARGP to STREAM; if POST is false, then 1579 everything preceding a '\v' character in the documentation strings (or 1580 the whole string, for those with none) is printed, otherwise, everything 1581 following the '\v' character (nothing for strings without). Each separate 1582 bit of documentation is separated a blank line, and if PRE_BLANK is true, 1583 then the first is as well. If FIRST_ONLY is true, only the first 1584 occurrence is output. Returns true if anything was output. */ 1585 static int 1586 argp_doc (const struct argp *argp, const struct argp_state *state, 1587 int post, int pre_blank, int first_only, 1588 argp_fmtstream_t stream) 1589 { 1590 const char *text; 1591 const char *inp_text; 1592 void *input = 0; 1593 int anything = 0; 1594 size_t inp_text_limit = 0; 1595 const char *doc = argp->doc ? dgettext (argp->argp_domain, argp->doc) : NULL; 1596 const struct argp_child *child = argp->children; 1597 1598 if (doc) 1599 { 1600 char *vt = strchr (doc, '\v'); 1601 inp_text = post ? (vt ? vt + 1 : 0) : doc; 1602 inp_text_limit = (!post && vt) ? (vt - doc) : 0; 1603 } 1604 else 1605 inp_text = 0; 1606 1607 if (argp->help_filter) 1608 /* We have to filter the doc strings. */ 1609 { 1610 if (inp_text_limit) 1611 /* Copy INP_TEXT so that it's nul-terminated. */ 1612 inp_text = __strndup (inp_text, inp_text_limit); 1613 input = __argp_input (argp, state); 1614 text = 1615 (*argp->help_filter) (post 1616 ? ARGP_KEY_HELP_POST_DOC 1617 : ARGP_KEY_HELP_PRE_DOC, 1618 inp_text, input); 1619 } 1620 else 1621 text = (const char *) inp_text; 1622 1623 if (text) 1624 { 1625 if (pre_blank) 1626 __argp_fmtstream_putc (stream, '\n'); 1627 1628 if (text == inp_text && inp_text_limit) 1629 __argp_fmtstream_write (stream, inp_text, inp_text_limit); 1630 else 1631 __argp_fmtstream_puts (stream, text); 1632 1633 if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream)) 1634 __argp_fmtstream_putc (stream, '\n'); 1635 1636 anything = 1; 1637 } 1638 1639 if (text && text != inp_text) 1640 free ((char *) text); /* Free TEXT returned from the help filter. */ 1641 if (inp_text && inp_text_limit && argp->help_filter) 1642 free ((char *) inp_text); /* We copied INP_TEXT, so free it now. */ 1643 1644 if (post && argp->help_filter) 1645 /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text. */ 1646 { 1647 text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input); 1648 if (text) 1649 { 1650 if (anything || pre_blank) 1651 __argp_fmtstream_putc (stream, '\n'); 1652 __argp_fmtstream_puts (stream, text); 1653 free ((char *) text); 1654 if (__argp_fmtstream_point (stream) 1655 > __argp_fmtstream_lmargin (stream)) 1656 __argp_fmtstream_putc (stream, '\n'); 1657 anything = 1; 1658 } 1659 } 1660 1661 if (child) 1662 while (child->argp && !(first_only && anything)) 1663 anything |= 1664 argp_doc ((child++)->argp, state, 1665 post, anything || pre_blank, first_only, 1666 stream); 1667 1668 return anything; 1669 } 1670 1671 /* Output a usage message for ARGP to STREAM. If called from 1672 argp_state_help, STATE is the relevant parsing state. FLAGS are from the 1673 set ARGP_HELP_*. NAME is what to use wherever a 'program name' is 1674 needed. */ 1675 static void 1676 _help (const struct argp *argp, const struct argp_state *state, FILE *stream, 1677 unsigned flags, char *name) 1678 { 1679 int anything = 0; /* Whether we've output anything. */ 1680 struct hol *hol = 0; 1681 argp_fmtstream_t fs; 1682 1683 if (! stream) 1684 return; 1685 1686 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) 1687 __flockfile (stream); 1688 #endif 1689 1690 if (! uparams.valid) 1691 fill_in_uparams (state); 1692 1693 fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0); 1694 if (! fs) 1695 { 1696 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) 1697 __funlockfile (stream); 1698 #endif 1699 return; 1700 } 1701 1702 if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG)) 1703 { 1704 hol = argp_hol (argp, 0); 1705 1706 /* If present, these options always come last. */ 1707 hol_set_group (hol, "help", -1); 1708 hol_set_group (hol, "version", -1); 1709 1710 hol_sort (hol); 1711 } 1712 1713 if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE)) 1714 /* Print a short "Usage:" message. */ 1715 { 1716 int first_pattern = 1, more_patterns; 1717 size_t num_pattern_levels = argp_args_levels (argp); 1718 char *pattern_levels = alloca (num_pattern_levels); 1719 1720 memset (pattern_levels, 0, num_pattern_levels); 1721 1722 do 1723 { 1724 int old_lm; 1725 int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent); 1726 char *levels = pattern_levels; 1727 1728 if (first_pattern) 1729 __argp_fmtstream_printf (fs, "%s %s", 1730 dgettext (argp->argp_domain, "Usage:"), 1731 name); 1732 else 1733 __argp_fmtstream_printf (fs, "%s %s", 1734 dgettext (argp->argp_domain, " or: "), 1735 name); 1736 1737 /* We set the lmargin as well as the wmargin, because hol_usage 1738 manually wraps options with newline to avoid annoying breaks. */ 1739 old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent); 1740 1741 if (flags & ARGP_HELP_SHORT_USAGE) 1742 /* Just show where the options go. */ 1743 { 1744 if (hol->num_entries > 0) 1745 __argp_fmtstream_puts (fs, dgettext (argp->argp_domain, 1746 " [OPTION...]")); 1747 } 1748 else 1749 /* Actually print the options. */ 1750 { 1751 hol_usage (hol, fs); 1752 flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once. */ 1753 } 1754 1755 more_patterns = argp_args_usage (argp, state, &levels, 1, fs); 1756 1757 __argp_fmtstream_set_wmargin (fs, old_wm); 1758 __argp_fmtstream_set_lmargin (fs, old_lm); 1759 1760 __argp_fmtstream_putc (fs, '\n'); 1761 anything = 1; 1762 1763 first_pattern = 0; 1764 } 1765 while (more_patterns); 1766 } 1767 1768 if (flags & ARGP_HELP_PRE_DOC) 1769 anything |= argp_doc (argp, state, 0, 0, 1, fs); 1770 1771 if (flags & ARGP_HELP_SEE) 1772 { 1773 __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\ 1774 Try '%s --help' or '%s --usage' for more information.\n"), 1775 name, name); 1776 anything = 1; 1777 } 1778 1779 if (flags & ARGP_HELP_LONG) 1780 /* Print a long, detailed help message. */ 1781 { 1782 /* Print info about all the options. */ 1783 if (hol->num_entries > 0) 1784 { 1785 if (anything) 1786 __argp_fmtstream_putc (fs, '\n'); 1787 hol_help (hol, state, fs); 1788 anything = 1; 1789 } 1790 } 1791 1792 if (flags & ARGP_HELP_POST_DOC) 1793 /* Print any documentation strings at the end. */ 1794 anything |= argp_doc (argp, state, 1, anything, 0, fs); 1795 1796 if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address) 1797 { 1798 if (anything) 1799 __argp_fmtstream_putc (fs, '\n'); 1800 __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, 1801 "Report bugs to %s.\n"), 1802 argp_program_bug_address); 1803 anything = 1; 1804 } 1805 1806 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) 1807 __funlockfile (stream); 1808 #endif 1809 1810 if (hol) 1811 hol_free (hol); 1812 1813 __argp_fmtstream_free (fs); 1814 } 1815 1816 /* Output a usage message for ARGP to STREAM. FLAGS are from the set 1817 ARGP_HELP_*. NAME is what to use wherever a 'program name' is needed. */ 1818 void __argp_help (const struct argp *argp, FILE *stream, 1819 unsigned flags, char *name) 1820 { 1821 _help (argp, 0, stream, flags, name); 1822 } 1823 #ifdef weak_alias 1824 weak_alias (__argp_help, argp_help) 1825 #endif 1826 1827 #if ! (defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME) 1828 char * 1829 __argp_short_program_name (void) 1830 { 1831 # if HAVE_DECL_PROGRAM_INVOCATION_NAME 1832 char *name = strrchr (program_invocation_name, '/'); 1833 return name ? name + 1 : program_invocation_name; 1834 # else 1835 /* FIXME: What now? Miles suggests that it is better to use NULL, 1836 but currently the value is passed on directly to fputs_unlocked, 1837 so that requires more changes. */ 1838 # if __GNUC__ || (__clang_major__ >= 4) 1839 # warning No reasonable value to return 1840 # endif /* __GNUC__ */ 1841 return ""; 1842 # endif 1843 } 1844 #endif 1845 1846 /* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are 1847 from the set ARGP_HELP_*. */ 1848 void 1849 __argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags) 1850 { 1851 if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream) 1852 { 1853 if (state && (state->flags & ARGP_LONG_ONLY)) 1854 flags |= ARGP_HELP_LONG_ONLY; 1855 1856 _help (state ? state->root_argp : 0, state, stream, flags, 1857 state ? state->name : __argp_short_program_name ()); 1858 1859 if (!state || ! (state->flags & ARGP_NO_EXIT)) 1860 { 1861 if (flags & ARGP_HELP_EXIT_ERR) 1862 exit (argp_err_exit_status); 1863 if (flags & ARGP_HELP_EXIT_OK) 1864 exit (0); 1865 } 1866 } 1867 } 1868 #ifdef weak_alias 1869 weak_alias (__argp_state_help, argp_state_help) 1870 #endif 1871 1872 /* If appropriate, print the printf string FMT and following args, preceded 1873 by the program name and ':', to stderr, and followed by a "Try ... --help" 1874 message, then exit (1). */ 1875 void 1876 __argp_error (const struct argp_state *state, const char *fmt, ...) 1877 { 1878 if (!state || !(state->flags & ARGP_NO_ERRS)) 1879 { 1880 FILE *stream = state ? state->err_stream : stderr; 1881 1882 if (stream) 1883 { 1884 va_list ap; 1885 1886 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) 1887 __flockfile (stream); 1888 #endif 1889 1890 va_start (ap, fmt); 1891 1892 #ifdef _LIBC 1893 char *buf; 1894 1895 if (_IO_vasprintf (&buf, fmt, ap) < 0) 1896 buf = NULL; 1897 1898 __fxprintf (stream, "%s: %s\n", 1899 state ? state->name : __argp_short_program_name (), buf); 1900 1901 free (buf); 1902 #else 1903 fputs_unlocked (state ? state->name : __argp_short_program_name (), 1904 stream); 1905 putc_unlocked (':', stream); 1906 putc_unlocked (' ', stream); 1907 1908 vfprintf (stream, fmt, ap); 1909 1910 putc_unlocked ('\n', stream); 1911 #endif 1912 1913 __argp_state_help (state, stream, ARGP_HELP_STD_ERR); 1914 1915 va_end (ap); 1916 1917 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) 1918 __funlockfile (stream); 1919 #endif 1920 } 1921 } 1922 } 1923 #ifdef weak_alias 1924 weak_alias (__argp_error, argp_error) 1925 #endif 1926 1927 /* Similar to the standard gnu error-reporting function error(), but will 1928 respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print 1929 to STATE->err_stream. This is useful for argument parsing code that is 1930 shared between program startup (when exiting is desired) and runtime 1931 option parsing (when typically an error code is returned instead). The 1932 difference between this function and argp_error is that the latter is for 1933 *parsing errors*, and the former is for other problems that occur during 1934 parsing but don't reflect a (syntactic) problem with the input. */ 1935 void 1936 __argp_failure (const struct argp_state *state, int status, int errnum, 1937 const char *fmt, ...) 1938 { 1939 if (!state || !(state->flags & ARGP_NO_ERRS)) 1940 { 1941 FILE *stream = state ? state->err_stream : stderr; 1942 1943 if (stream) 1944 { 1945 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) 1946 __flockfile (stream); 1947 #endif 1948 1949 #ifdef _LIBC 1950 __fxprintf (stream, "%s", 1951 state ? state->name : __argp_short_program_name ()); 1952 #else 1953 fputs_unlocked (state ? state->name : __argp_short_program_name (), 1954 stream); 1955 #endif 1956 1957 if (fmt) 1958 { 1959 va_list ap; 1960 1961 va_start (ap, fmt); 1962 #ifdef _LIBC 1963 char *buf; 1964 1965 if (_IO_vasprintf (&buf, fmt, ap) < 0) 1966 buf = NULL; 1967 1968 __fxprintf (stream, ": %s", buf); 1969 1970 free (buf); 1971 #else 1972 putc_unlocked (':', stream); 1973 putc_unlocked (' ', stream); 1974 1975 vfprintf (stream, fmt, ap); 1976 #endif 1977 1978 va_end (ap); 1979 } 1980 1981 if (errnum) 1982 { 1983 char buf[200]; 1984 1985 #ifdef _LIBC 1986 __fxprintf (stream, ": %s", 1987 __strerror_r (errnum, buf, sizeof (buf))); 1988 #else 1989 char const *s = NULL; 1990 putc_unlocked (':', stream); 1991 putc_unlocked (' ', stream); 1992 # if GNULIB_STRERROR_R_POSIX || HAVE_DECL_STRERROR_R 1993 # if !GNULIB_STRERROR_R_POSIX && STRERROR_R_CHAR_P 1994 s = __strerror_r (errnum, buf, sizeof buf); 1995 # else 1996 if (__strerror_r (errnum, buf, sizeof buf) == 0) 1997 s = buf; 1998 # endif 1999 # endif 2000 if (! s && ! (s = strerror (errnum))) 2001 s = dgettext (state->root_argp->argp_domain, 2002 "Unknown system error"); 2003 fputs_unlocked (s, stream); 2004 #endif 2005 } 2006 2007 #if _LIBC 2008 if (_IO_fwide (stream, 0) > 0) 2009 putwc_unlocked (L'\n', stream); 2010 else 2011 #endif 2012 putc_unlocked ('\n', stream); 2013 2014 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) 2015 __funlockfile (stream); 2016 #endif 2017 2018 if (status && (!state || !(state->flags & ARGP_NO_EXIT))) 2019 exit (status); 2020 } 2021 } 2022 } 2023 #ifdef weak_alias 2024 weak_alias (__argp_failure, argp_failure) 2025 #endif 2026