popt  1.18
popthelp.c
Go to the documentation of this file.
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 
7 /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
8  file accompanying popt source distributions, available from
9  ftp://ftp.rpm.org/pub/rpm/dist. */
10 
11 #include "system.h"
12 
13 #define POPT_USE_TIOCGWINSZ
14 #ifdef POPT_USE_TIOCGWINSZ
15 #include <sys/ioctl.h>
16 #endif
17 
18 #define POPT_WCHAR_HACK
19 #ifdef POPT_WCHAR_HACK
20 #include <wchar.h> /* for mbsrtowcs */
21 #endif
22 #include "poptint.h"
23 
24 
33 static void displayArgs(poptContext con,
34  UNUSED(enum poptCallbackReason foo),
35  struct poptOption * key,
36  UNUSED(const char * arg),
37  UNUSED(void * data))
38 {
39  if (key->shortName == '?')
40  poptPrintHelp(con, stdout, 0);
41  else
42  poptPrintUsage(con, stdout, 0);
43 
44  con = poptFreeContext(con);
45  exit(0);
46 }
47 
48 #ifdef NOTYET
49 static int show_option_defaults = 0;
50 #endif
51 
55 struct poptOption poptAliasOptions[] = {
57 };
58 
62 struct poptOption poptHelpOptions[] = {
63  { NULL, '\0', POPT_ARG_CALLBACK, (void *)displayArgs, 0, NULL, NULL },
64  { "help", '?', 0, NULL, (int)'?', N_("Show this help message"), NULL },
65  { "usage", '\0', 0, NULL, (int)'u', N_("Display brief usage message"), NULL },
67 } ;
68 
69 static struct poptOption poptHelpOptions2[] = {
70  { NULL, '\0', POPT_ARG_INTL_DOMAIN, PACKAGE, 0, NULL, NULL},
71  { NULL, '\0', POPT_ARG_CALLBACK, (void *)displayArgs, 0, NULL, NULL },
72  { "help", '?', 0, NULL, (int)'?', N_("Show this help message"), NULL },
73  { "usage", '\0', 0, NULL, (int)'u', N_("Display brief usage message"), NULL },
74 #ifdef NOTYET
75  { "defaults", '\0', POPT_ARG_NONE, &show_option_defaults, 0,
76  N_("Display option defaults in message"), NULL },
77 #endif
78  { NULL, '\0', 0, NULL, 0, N_("Terminate options"), NULL },
80 } ;
81 
83 
84 #define _POPTHELP_MAXLINE ((size_t)79)
85 
86 typedef struct columns_s {
87  size_t cur;
88  size_t max;
90 
96 static size_t maxColumnWidth(FILE *fp)
97 {
98  size_t maxcols = _POPTHELP_MAXLINE;
99 #if defined(TIOCGWINSZ)
100  struct winsize ws;
101  int fdno = fileno(fp ? fp : stdout);
102 
103  memset(&ws, 0, sizeof(ws));
104  if (fdno >= 0 && !ioctl(fdno, (unsigned long)TIOCGWINSZ, &ws)) {
105  size_t ws_col = (size_t)ws.ws_col;
106  if (ws_col > maxcols && ws_col < (size_t)256)
107  maxcols = ws_col - 1;
108  }
109 #endif
110  return maxcols;
111 }
112 
118 static inline size_t stringDisplayWidth(const char *s)
119 {
120  size_t n = strlen(s);
121 #ifdef POPT_WCHAR_HACK
122  mbstate_t t;
123 
124  memset ((void *)&t, 0, sizeof (t)); /* In initial state. */
125  /* Determine number of display characters. */
126  n = mbsrtowcs (NULL, &s, n, &t);
127 #else
128  n = 0;
129  for (; *s; s = POPT_next_char(s))
130  n++;
131 #endif
132 
133  return n;
134 }
135 
139 static const char *
141 {
142  if (opt != NULL)
143  for (; opt->longName || opt->shortName || opt->arg; opt++) {
144  if (opt->argInfo == POPT_ARG_INTL_DOMAIN)
145  return opt->arg;
146  }
147  return NULL;
148 }
149 
154 static const char *
155 getArgDescrip(const struct poptOption * opt,
156  /* FIX: i18n macros disabled with lclint */
157  const char * translation_domain)
158 {
159  if (!poptArgType(opt)) return NULL;
160 
161  if (poptArgType(opt) == POPT_ARG_MAINCALL)
162  return opt->argDescrip;
163  if (poptArgType(opt) == POPT_ARG_ARGV)
164  return opt->argDescrip;
165 
166  if (opt->argDescrip) {
167  /* Some strings need popt library, not application, i18n domain. */
168  if (opt == (poptHelpOptions + 1)
169  || opt == (poptHelpOptions + 2)
170  || !strcmp(opt->argDescrip, N_("Help options:"))
171  || !strcmp(opt->argDescrip, N_("Options implemented via popt alias/exec:")))
172  return POPT_(opt->argDescrip);
173 
174  /* Use the application i18n domain. */
175  return D_(translation_domain, opt->argDescrip);
176  }
177 
178  switch (poptArgType(opt)) {
179  case POPT_ARG_NONE: return POPT_("NONE");
180 #ifdef DYING
181  case POPT_ARG_VAL: return POPT_("VAL");
182 #else
183  case POPT_ARG_VAL: return NULL;
184 #endif
185  case POPT_ARG_INT: return POPT_("INT");
186  case POPT_ARG_SHORT: return POPT_("SHORT");
187  case POPT_ARG_LONG: return POPT_("LONG");
188  case POPT_ARG_LONGLONG: return POPT_("LONGLONG");
189  case POPT_ARG_STRING: return POPT_("STRING");
190  case POPT_ARG_FLOAT: return POPT_("FLOAT");
191  case POPT_ARG_DOUBLE: return POPT_("DOUBLE");
192  case POPT_ARG_MAINCALL: return NULL;
193  case POPT_ARG_ARGV: return NULL;
194  default: return POPT_("ARG");
195  }
196 }
197 
205 static char *
206 singleOptionDefaultValue(size_t lineLength,
207  const struct poptOption * opt,
208  /* FIX: i18n macros disabled with lclint */
209  const char * translation_domain)
210 {
211  const char * defstr = D_(translation_domain, "default");
212  char * le = malloc(4*lineLength + 1);
213  char * l = le;
214 
215  if (le == NULL) return NULL; /* XXX can't happen */
216  *le = '\0';
217  *le++ = '(';
218  le = stpcpy(le, defstr);
219  *le++ = ':';
220  *le++ = ' ';
221  if (opt->arg) { /* XXX programmer error */
222  poptArg arg = { .ptr = opt->arg };
223  switch (poptArgType(opt)) {
224  case POPT_ARG_VAL:
225  case POPT_ARG_INT:
226  le += sprintf(le, "%d", arg.intp[0]);
227  break;
228  case POPT_ARG_SHORT:
229  le += sprintf(le, "%hd", arg.shortp[0]);
230  break;
231  case POPT_ARG_LONG:
232  le += sprintf(le, "%ld", arg.longp[0]);
233  break;
234  case POPT_ARG_LONGLONG:
235  le += sprintf(le, "%lld", arg.longlongp[0]);
236  break;
237  case POPT_ARG_FLOAT:
238  { double aDouble = (double) arg.floatp[0];
239  le += sprintf(le, "%g", aDouble);
240  } break;
241  case POPT_ARG_DOUBLE:
242  le += sprintf(le, "%g", arg.doublep[0]);
243  break;
244  case POPT_ARG_MAINCALL:
245  le += sprintf(le, "%p", opt->arg);
246  break;
247  case POPT_ARG_ARGV:
248  le += sprintf(le, "%p", opt->arg);
249  break;
250  case POPT_ARG_STRING:
251  { const char * s = arg.argv[0];
252  if (s == NULL)
253  le = stpcpy(le, "null");
254  else {
255  size_t limit = 4*lineLength - (le - l) - sizeof("\"\")");
256  size_t slen;
257  *le++ = '"';
258  strncpy(le, s, limit); le[limit] = '\0'; le += (slen = strlen(le));
259  if (slen == limit && s[limit])
260  le[-1] = le[-2] = le[-3] = '.';
261  *le++ = '"';
262  }
263  } break;
264  case POPT_ARG_NONE:
265  default:
266  l = _free(l);
267  return NULL;
268  break;
269  }
270  }
271  *le++ = ')';
272  *le = '\0';
273 
274  return l;
275 }
276 
284 static void singleOptionHelp(FILE * fp, columns_t columns,
285  const struct poptOption * opt,
286  const char * translation_domain)
287 {
288  size_t maxLeftCol = columns->cur;
289  size_t indentLength = maxLeftCol + 5;
290  size_t lineLength = columns->max - indentLength;
291  const char * help = D_(translation_domain, opt->descrip);
292  const char * argDescrip = getArgDescrip(opt, translation_domain);
293  /* Display shortName iff printable non-space. */
294  int prtshort = (int)(isprint((int)opt->shortName) && opt->shortName != ' ');
295  size_t helpLength;
296  char * defs = NULL;
297  char * left;
298  size_t nb = maxLeftCol + 1;
299  int displaypad = 0;
300 
301  /* Make sure there's more than enough room in target buffer. */
302  if (opt->longName) nb += strlen(opt->longName);
303  if (F_ISSET(opt, TOGGLE)) nb += sizeof("[no]") - 1;
304  if (argDescrip) nb += strlen(argDescrip);
305 
306  left = malloc(nb);
307  if (left == NULL) return; /* XXX can't happen */
308  left[0] = '\0';
309  left[maxLeftCol] = '\0';
310 
311 #define prtlong (opt->longName != NULL) /* XXX splint needs a clue */
312  if (!(prtshort || prtlong))
313  goto out;
314  if (prtshort && prtlong) {
315  char *dash = F_ISSET(opt, ONEDASH) ? "-" : "--";
316  left[0] = '-';
317  left[1] = opt->shortName;
318  (void) stpcpy(stpcpy(stpcpy(left+2, ", "), dash), opt->longName);
319  } else if (prtshort) {
320  left[0] = '-';
321  left[1] = opt->shortName;
322  left[2] = '\0';
323  } else if (prtlong) {
324  /* XXX --long always padded for alignment with/without "-X, ". */
325  char *dash = poptArgType(opt) == POPT_ARG_MAINCALL ? ""
326  : (F_ISSET(opt, ONEDASH) ? "-" : "--");
327  const char *longName = opt->longName;
328  const char *toggle;
329  if (F_ISSET(opt, TOGGLE)) {
330  toggle = "[no]";
331  if (longName[0] == 'n' && longName[1] == 'o') {
332  longName += sizeof("no") - 1;
333  if (longName[0] == '-')
334  longName++;
335  }
336  } else
337  toggle = "";
338  (void) stpcpy(stpcpy(stpcpy(stpcpy(left, " "), dash), toggle), longName);
339  }
340 #undef prtlong
341 
342  if (argDescrip) {
343  char * le = left + strlen(left);
344 
345  if (F_ISSET(opt, OPTIONAL))
346  *le++ = '[';
347 
348  /* Choose type of output */
349  if (F_ISSET(opt, SHOW_DEFAULT)) {
350  defs = singleOptionDefaultValue(lineLength, opt, translation_domain);
351  if (defs) {
352  char * t = malloc((help ? strlen(help) : 0) +
353  strlen(defs) + sizeof(" "));
354  if (t) {
355  char * te = t;
356  if (help)
357  te = stpcpy(te, help);
358  *te++ = ' ';
359  strcpy(te, defs);
360  defs = _free(defs);
361  defs = t;
362  }
363  }
364  }
365 
366  if (opt->argDescrip == NULL) {
367  switch (poptArgType(opt)) {
368  case POPT_ARG_NONE:
369  break;
370  case POPT_ARG_VAL:
371 #ifdef NOTNOW /* XXX pug ugly nerdy output */
372  { long aLong = opt->val;
373  int ops = F_ISSET(opt, LOGICALOPS);
374  int negate = F_ISSET(opt, NOT);
375 
376  /* Don't bother displaying typical values */
377  if (!ops && (aLong == 0L || aLong == 1L || aLong == -1L))
378  break;
379  *le++ = '[';
380  switch (ops) {
381  case POPT_ARGFLAG_OR:
382  *le++ = '|';
383  break;
384  case POPT_ARGFLAG_AND:
385  *le++ = '&';
386  break;
387  case POPT_ARGFLAG_XOR:
388  *le++ = '^';
389  break;
390  default:
391  break;
392  }
393  *le++ = (opt->longName != NULL ? '=' : ' ');
394  if (negate) *le++ = '~';
395  le += sprintf(le, (ops ? "0x%lx" : "%ld"), aLong);
396  *le++ = ']';
397  }
398 #endif
399  break;
400  case POPT_ARG_INT:
401  case POPT_ARG_SHORT:
402  case POPT_ARG_LONG:
403  case POPT_ARG_LONGLONG:
404  case POPT_ARG_FLOAT:
405  case POPT_ARG_DOUBLE:
406  case POPT_ARG_STRING:
407  *le++ = (opt->longName != NULL ? '=' : ' ');
408  le = stpcpy(le, argDescrip);
409  break;
410  default:
411  break;
412  }
413  } else {
414  char *leo;
415 
416  /* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */
417  if (!strchr(" =(", argDescrip[0]))
418  *le++ = ((poptArgType(opt) == POPT_ARG_MAINCALL) ? ' ' :
419  (poptArgType(opt) == POPT_ARG_ARGV) ? ' ' : '=');
420  le = stpcpy(leo = le, argDescrip);
421 
422  /* Adjust for (possible) wide characters. */
423  displaypad = (int)((le - leo) - stringDisplayWidth(argDescrip));
424  }
425  if (F_ISSET(opt, OPTIONAL))
426  *le++ = ']';
427  *le = '\0';
428  }
429 
430  if (help)
431  POPT_fprintf(fp," %-*s ", (int)(maxLeftCol+displaypad), left);
432  else {
433  POPT_fprintf(fp," %s\n", left);
434  goto out;
435  }
436 
437  left = _free(left);
438  if (defs)
439  help = defs;
440 
441  helpLength = strlen(help);
442  while (helpLength > lineLength) {
443  const char * ch;
444  char format[16];
445 
446  ch = help + lineLength - 1;
447  while (ch > help && !_isspaceptr(ch))
448  ch = POPT_prev_char(ch);
449  if (ch == help) break; /* give up */
450  while (ch > (help + 1) && _isspaceptr(ch))
451  ch = POPT_prev_char (ch);
452  ch = POPT_next_char(ch);
453 
454  /*
455  * XXX strdup is necessary to add NUL terminator so that an unknown
456  * no. of (possible) multi-byte characters can be displayed.
457  */
458  { char * fmthelp = xstrdup(help);
459  if (fmthelp) {
460  fmthelp[ch - help] = '\0';
461  sprintf(format, "%%s\n%%%ds", (int) indentLength);
462  POPT_fprintf(fp, format, fmthelp, " ");
463  free(fmthelp);
464  }
465  }
466 
467  help = ch;
468  while (_isspaceptr(help) && *help)
469  help = POPT_next_char(help);
470  helpLength = strlen(help);
471  }
472 
473  if (helpLength) fprintf(fp, "%s\n", help);
474  help = NULL;
475 
476 out:
477  defs = _free(defs);
478  left = _free(left);
479 }
480 
487 static size_t maxArgWidth(const struct poptOption * opt,
488  const char * translation_domain)
489 {
490  size_t max = 0;
491  size_t len = 0;
492  const char * argDescrip;
493 
494  if (opt != NULL)
495  while (opt->longName || opt->shortName || opt->arg) {
496  if (poptArgType(opt) == POPT_ARG_INCLUDE_TABLE) {
497  void * arg = opt->arg;
498  /* XXX sick hack to preserve pretense of ABI. */
499  if (arg == poptHelpOptions)
500  arg = poptHelpOptionsI18N;
501  if (arg) /* XXX program error */
502  len = maxArgWidth(arg, translation_domain);
503  if (len > max) max = len;
504  } else if (!F_ISSET(opt, DOC_HIDDEN)) {
505  len = sizeof(" ")-1;
506  /* XXX --long always padded for alignment with/without "-X, ". */
507  len += sizeof("-X, ")-1;
508  if (opt->longName) {
509  len += (F_ISSET(opt, ONEDASH) ? sizeof("-") : sizeof("--")) - 1;
510  len += strlen(opt->longName);
511  }
512 
513  argDescrip = getArgDescrip(opt, translation_domain);
514 
515  if (argDescrip) {
516 
517  /* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */
518  if (!strchr(" =(", argDescrip[0])) len += sizeof("=")-1;
519 
520  /* Adjust for (possible) wide characters. */
521  len += stringDisplayWidth(argDescrip);
522  }
523 
524  if (F_ISSET(opt, OPTIONAL)) len += sizeof("[]")-1;
525  if (len > max) max = len;
526  }
527  opt++;
528  }
529 
530  return max;
531 }
532 
541 static void itemHelp(FILE * fp,
542  poptItem items, int nitems,
543  columns_t columns,
544  const char * translation_domain)
545 {
546  poptItem item;
547  int i;
548 
549  if (items != NULL)
550  for (i = 0, item = items; i < nitems; i++, item++) {
551  const struct poptOption * opt;
552  opt = &item->option;
553  if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN))
554  singleOptionHelp(fp, columns, opt, translation_domain);
555  }
556 }
557 
566 static void singleTableHelp(poptContext con, FILE * fp,
567  const struct poptOption * table,
568  columns_t columns,
569  const char * translation_domain)
570 {
571  const struct poptOption * opt;
572  const char *sub_transdom;
573 
574  if (con == NULL) return;
575 
576  if (table == poptAliasOptions) {
577  itemHelp(fp, con->aliases, con->numAliases, columns, NULL);
578  itemHelp(fp, con->execs, con->numExecs, columns, NULL);
579  return;
580  }
581 
582  if (table != NULL)
583  for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) {
584  if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN))
585  singleOptionHelp(fp, columns, opt, translation_domain);
586  }
587 
588  if (table != NULL)
589  for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) {
590  void * arg = opt->arg;
592  continue;
593  /* XXX sick hack to preserve pretense of ABI. */
594  if (arg == poptHelpOptions)
596  sub_transdom = getTableTranslationDomain(arg);
597  if (sub_transdom == NULL)
598  sub_transdom = translation_domain;
599 
600  /* If no popt aliases/execs, skip poptAliasOption processing. */
601  if (arg == poptAliasOptions && !(con->numAliases || con->numExecs))
602  continue;
603  if (opt->descrip)
604  POPT_fprintf(fp, "\n%s\n", D_(sub_transdom, opt->descrip));
605 
606  singleTableHelp(con, fp, arg, columns, sub_transdom);
607  }
608 }
609 
614 static size_t showHelpIntro(poptContext con, FILE * fp)
615 {
616  size_t len = (size_t)6;
617 
618  POPT_fprintf(fp, POPT_("Usage:"));
619  if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
620  struct optionStackEntry * os = con->optionStack;
621  const char * fn = (os->argv ? os->argv[0] : NULL);
622  if (fn == NULL) return len;
623  if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1;
624  /* XXX POPT_fprintf not needed for argv[0] display. */
625  fprintf(fp, " %s", fn);
626  len += strlen(fn) + 1;
627  }
628 
629  return len;
630 }
631 
632 void poptPrintHelp(poptContext con, FILE * fp, UNUSED(int flags))
633 {
634  columns_t columns = calloc((size_t)1, sizeof(*columns));
635 
636  if (con == NULL) return;
637 
638  (void) showHelpIntro(con, fp);
639  if (con->otherHelp)
640  POPT_fprintf(fp, " %s\n", con->otherHelp);
641  else
642  POPT_fprintf(fp, " %s\n", POPT_("[OPTION...]"));
643 
644  if (columns) {
645  columns->cur = maxArgWidth(con->options, NULL);
646  columns->max = maxColumnWidth(fp);
647  singleTableHelp(con, fp, con->options, columns, NULL);
648  free(columns);
649  }
650 }
651 
659 static size_t singleOptionUsage(FILE * fp, columns_t columns,
660  const struct poptOption * opt,
661  const char *translation_domain)
662 {
663  size_t len = sizeof(" []")-1;
664  const char * argDescrip = getArgDescrip(opt, translation_domain);
665  /* Display shortName iff printable non-space. */
666  int prtshort = (int)(isprint((int)opt->shortName) && opt->shortName != ' ');
667 
668 #define prtlong (opt->longName != NULL) /* XXX splint needs a clue */
669  if (!(prtshort || prtlong))
670  return columns->cur;
671 
672  len = sizeof(" []")-1;
673  if (prtshort)
674  len += sizeof("-c")-1;
675  if (prtlong) {
676  if (prtshort) len += sizeof("|")-1;
677  len += (F_ISSET(opt, ONEDASH) ? sizeof("-") : sizeof("--")) - 1;
678  len += strlen(opt->longName);
679  }
680 
681  if (argDescrip) {
682 
683  /* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */
684  if (!strchr(" =(", argDescrip[0])) len += sizeof("=")-1;
685 
686  /* Adjust for (possible) wide characters. */
687  len += stringDisplayWidth(argDescrip);
688  }
689 
690  if ((columns->cur + len) > columns->max) {
691  fprintf(fp, "\n ");
692  columns->cur = (size_t)7;
693  }
694 
695  fprintf(fp, " [");
696  if (prtshort)
697  fprintf(fp, "-%c", opt->shortName);
698  if (prtlong)
699  fprintf(fp, "%s%s%s",
700  (prtshort ? "|" : ""),
701  (F_ISSET(opt, ONEDASH) ? "-" : "--"),
702  opt->longName);
703 #undef prtlong
704 
705  if (argDescrip) {
706  /* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */
707  if (!strchr(" =(", argDescrip[0])) fprintf(fp, "=");
708  fprintf(fp, "%s", argDescrip);
709  }
710  fprintf(fp, "]");
711 
712  return columns->cur + len + 1;
713 }
714 
723 static size_t itemUsage(FILE * fp, columns_t columns,
724  poptItem item, int nitems,
725  const char * translation_domain)
726 {
727  int i;
728 
729  if (item != NULL)
730  for (i = 0; i < nitems; i++, item++) {
731  const struct poptOption * opt;
732  opt = &item->option;
733  if (poptArgType(opt) == POPT_ARG_INTL_DOMAIN) {
734  translation_domain = (const char *)opt->arg;
735  } else
736  if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN)) {
737  columns->cur = singleOptionUsage(fp, columns, opt, translation_domain);
738  }
739  }
740 
741  return columns->cur;
742 }
743 
747 typedef struct poptDone_s {
748  int nopts;
749  int maxopts;
750  const void ** opts;
752 
763 static size_t singleTableUsage(poptContext con, FILE * fp, columns_t columns,
764  const struct poptOption * opt,
765  const char * translation_domain,
766  poptDone done)
767 {
768  if (con != NULL && opt != NULL)
769  for (; (opt->longName || opt->shortName || opt->arg) ; opt++) {
770  if (poptArgType(opt) == POPT_ARG_INTL_DOMAIN) {
771  translation_domain = (const char *)opt->arg;
772  } else
773  if (poptArgType(opt) == POPT_ARG_INCLUDE_TABLE) {
774  void * arg = opt->arg;
775  /* XXX sick hack to preserve pretense of ABI. */
776  if (arg == poptHelpOptions)
777  arg = poptHelpOptionsI18N;
778  if (done) {
779  int i = 0;
780  if (done->opts != NULL)
781  for (i = 0; i < done->nopts; i++) {
782  const void * that = done->opts[i];
783  if (that == NULL || that != arg)
784  continue;
785  break;
786  }
787  /* Skip if this table has already been processed. */
788  if (arg == NULL || i < done->nopts)
789  continue;
790  if (done->opts != NULL && done->nopts < done->maxopts)
791  done->opts[done->nopts++] = (const void *) arg;
792  }
793  columns->cur = singleTableUsage(con, fp, columns, opt->arg,
794  translation_domain, done);
795  } else
796  if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN)) {
797  columns->cur = singleOptionUsage(fp, columns, opt, translation_domain);
798  }
799  }
800 
801  return columns->cur;
802 }
803 
812 static size_t showShortOptions(const struct poptOption * opt, FILE * fp,
813  char * str)
814 {
815  /* bufsize larger then the ascii set, lazy allocation on top level call. */
816  size_t nb = (size_t)300;
817  char * s = (str != NULL ? str : calloc((size_t)1, nb));
818  size_t len = (size_t)0;
819 
820  if (s == NULL)
821  return 0;
822 
823  if (opt != NULL)
824  for (; (opt->longName || opt->shortName || opt->arg); opt++) {
825  if (!F_ISSET(opt, DOC_HIDDEN) && opt->shortName && !poptArgType(opt))
826  {
827  /* Display shortName iff unique printable non-space. */
828  if (!strchr(s, opt->shortName) && isprint((int)opt->shortName)
829  && opt->shortName != ' ')
830  s[strlen(s)] = opt->shortName;
831  } else if (poptArgType(opt) == POPT_ARG_INCLUDE_TABLE) {
832  void * arg = opt->arg;
833  /* XXX sick hack to preserve pretense of ABI. */
834  if (arg == poptHelpOptions)
835  arg = poptHelpOptionsI18N;
836  if (arg) /* XXX program error */
837  len = showShortOptions(arg, fp, s);
838  }
839  }
840 
841  /* On return to top level, print the short options, return print length. */
842  if (s != str && *s != '\0') {
843  fprintf(fp, " [-%s]", s);
844  len = strlen(s) + sizeof(" [-]")-1;
845  }
846  if (s != str)
847  free(s);
848  return len;
849 }
850 
851 void poptPrintUsage(poptContext con, FILE * fp, UNUSED(int flags))
852 {
853  columns_t columns = calloc((size_t)1, sizeof(*columns));
854  struct poptDone_s done_buf;
855  poptDone done = &done_buf;
856 
857  if (con == NULL) return;
858 
859  memset(done, 0, sizeof(*done));
860  done->nopts = 0;
861  done->maxopts = 64;
862  if (columns) {
863  columns->cur = done->maxopts * sizeof(*done->opts);
864  columns->max = maxColumnWidth(fp);
865  done->opts = calloc((size_t)1, columns->cur);
866  if (done->opts != NULL)
867  done->opts[done->nopts++] = (const void *) con->options;
868 
869  columns->cur = showHelpIntro(con, fp);
870  columns->cur += showShortOptions(con->options, fp, NULL);
871  columns->cur = singleTableUsage(con, fp, columns, con->options, NULL, done);
872  columns->cur = itemUsage(fp, columns, con->aliases, con->numAliases, NULL);
873  columns->cur = itemUsage(fp, columns, con->execs, con->numExecs, NULL);
874 
875  if (con->otherHelp) {
876  columns->cur += strlen(con->otherHelp) + 1;
877  if (columns->cur > columns->max) fprintf(fp, "\n ");
878  fprintf(fp, " %s", con->otherHelp);
879  }
880 
881  fprintf(fp, "\n");
882  if (done->opts != NULL)
883  free(done->opts);
884  free(columns);
885  }
886 }
887 
888 void poptSetOtherOptionHelp(poptContext con, const char * text)
889 {
890  if (con == NULL) return;
891 
892  con->otherHelp = _free(con->otherHelp);
893  con->otherHelp = xstrdup(text);
894 }
poptContext poptFreeContext(poptContext con)
Destroy context.
Definition: popt.c:1531
#define POPT_CONTEXT_KEEP_FIRST
Definition: popt.h:120
#define POPT_ARG_DOUBLE
Definition: popt.h:35
#define POPT_ARG_VAL
Definition: popt.h:33
#define POPT_ARGFLAG_AND
Definition: popt.h:59
#define POPT_ARG_MAINCALL
Definition: popt.h:38
#define POPT_ARG_INTL_DOMAIN
Definition: popt.h:29
#define POPT_ARG_SHORT
Definition: popt.h:40
#define POPT_ARG_FLOAT
Definition: popt.h:34
#define POPT_ARGFLAG_OR
Definition: popt.h:57
#define POPT_ARG_INT
Definition: popt.h:22
#define POPT_ARG_LONG
Definition: popt.h:23
#define POPT_ARG_NONE
Definition: popt.h:20
#define POPT_ARG_STRING
Definition: popt.h:21
#define POPT_ARG_INCLUDE_TABLE
Definition: popt.h:24
#define POPT_ARGFLAG_XOR
Definition: popt.h:61
#define POPT_ARG_ARGV
Definition: popt.h:39
#define POPT_TABLEEND
Definition: popt.h:178
#define POPT_ARG_LONGLONG
Definition: popt.h:36
#define POPT_ARG_CALLBACK
Definition: popt.h:25
poptCallbackReason
Definition: popt.h:193
static size_t showShortOptions(const struct poptOption *opt, FILE *fp, char *str)
Return concatenated short options for display.
Definition: popthelp.c:812
struct poptOption poptHelpOptions[]
Auto help table options.
Definition: popthelp.c:62
static size_t maxArgWidth(const struct poptOption *opt, const char *translation_domain)
Find display width for longest argument string.
Definition: popthelp.c:487
static void itemHelp(FILE *fp, poptItem items, int nitems, columns_t columns, const char *translation_domain)
Display popt alias and exec help.
Definition: popthelp.c:541
static void singleOptionHelp(FILE *fp, columns_t columns, const struct poptOption *opt, const char *translation_domain)
Display help text for an option.
Definition: popthelp.c:284
static struct poptOption poptHelpOptions2[]
Definition: popthelp.c:69
struct columns_s * columns_t
static size_t singleOptionUsage(FILE *fp, columns_t columns, const struct poptOption *opt, const char *translation_domain)
Display usage text for an option.
Definition: popthelp.c:659
static void displayArgs(poptContext con, enum poptCallbackReason foo, struct poptOption *key, const char *arg, void *data)
Display arguments.
Definition: popthelp.c:33
void poptPrintHelp(poptContext con, FILE *fp, int flags)
Print detailed description of options.
Definition: popthelp.c:632
static const char * getTableTranslationDomain(const struct poptOption *opt)
Definition: popthelp.c:140
static size_t singleTableUsage(poptContext con, FILE *fp, columns_t columns, const struct poptOption *opt, const char *translation_domain, poptDone done)
Display usage text for a table of options.
Definition: popthelp.c:763
static size_t itemUsage(FILE *fp, columns_t columns, poptItem item, int nitems, const char *translation_domain)
Display popt alias and exec usage.
Definition: popthelp.c:723
static size_t showHelpIntro(poptContext con, FILE *fp)
Definition: popthelp.c:614
#define _POPTHELP_MAXLINE
Definition: popthelp.c:84
struct poptOption * poptHelpOptionsI18N
Definition: popthelp.c:82
static const char * getArgDescrip(const struct poptOption *opt, const char *translation_domain)
Definition: popthelp.c:155
struct poptOption poptAliasOptions[]
Empty table marker to enable displaying popt alias/exec options.
Definition: popthelp.c:55
static char * singleOptionDefaultValue(size_t lineLength, const struct poptOption *opt, const char *translation_domain)
Display default value for an option.
Definition: popthelp.c:206
void poptSetOtherOptionHelp(poptContext con, const char *text)
Provide text to replace default "[OPTION...]" in help/usage output.
Definition: popthelp.c:888
#define prtlong
static size_t stringDisplayWidth(const char *s)
Determine number of display characters in a string.
Definition: popthelp.c:118
static size_t maxColumnWidth(FILE *fp)
Return no.
Definition: popthelp.c:96
struct poptDone_s * poptDone
Keep track of option tables already processed.
static void singleTableHelp(poptContext con, FILE *fp, const struct poptOption *table, columns_t columns, const char *translation_domain)
Display help text for a table of options.
Definition: popthelp.c:566
void poptPrintUsage(poptContext con, FILE *fp, int flags)
Print terse description of options.
Definition: popthelp.c:851
const char * POPT_prev_char(const char *str)
Definition: poptint.c:15
const char * POPT_next_char(const char *str)
Definition: poptint.c:27
int POPT_fprintf(FILE *stream, const char *format,...)
Definition: poptint.c:138
#define POPT_(foo)
Definition: poptint.h:152
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: poptint.h:20
#define F_ISSET(_opt, _FLAG)
Definition: poptint.h:73
#define N_(foo)
Definition: poptint.h:155
#define D_(dom, str)
Definition: poptint.h:151
#define poptArgType(_opt)
Definition: poptint.h:70
size_t cur
Definition: popthelp.c:87
size_t max
Definition: popthelp.c:88
poptArgv argv
Definition: poptint.h:83
poptItem aliases
Definition: poptint.h:101
unsigned int flags
Definition: poptint.h:103
poptItem execs
Definition: poptint.h:104
const struct poptOption * options
Definition: poptint.h:98
int numExecs
Definition: poptint.h:105
const char * otherHelp
Definition: poptint.h:114
int numAliases
Definition: poptint.h:102
struct optionStackEntry optionStack[POPT_OPTION_DEPTH]
Definition: poptint.h:93
Keep track of option tables already processed.
Definition: popthelp.c:747
int maxopts
Definition: popthelp.c:749
const void ** opts
Definition: popthelp.c:750
int nopts
Definition: popthelp.c:748
A popt alias or exec argument for poptAddItem().
Definition: popt.h:150
struct poptOption option
Definition: popt.h:151
unsigned int argInfo
Definition: popt.h:130
void * arg
Definition: popt.h:131
char shortName
Definition: popt.h:129
const char * argDescrip
Definition: popt.h:134
int val
Definition: popt.h:132
const char * longName
Definition: popt.h:128
const char * descrip
Definition: popt.h:133
#define _isspaceptr(_chp)
Definition: system.h:12
#define UNUSED(x)
Definition: system.h:65
static char * stpcpy(char *dest, const char *src)
Definition: system.h:31
char * xstrdup(const char *str)
A union to simplify opt->arg access without casting.
Definition: poptint.h:54
const char ** argv
Definition: poptint.h:62
long * longp
Definition: poptint.h:58
long long * longlongp
Definition: poptint.h:59
short * shortp
Definition: poptint.h:57
int * intp
Definition: poptint.h:56
void * ptr
Definition: poptint.h:55
float * floatp
Definition: poptint.h:60
double * doublep
Definition: poptint.h:61