librnr  1.14.5
RoadNarrows Robotics Common Library 1
opts.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: RoadNarrows Robotics Common Library 1
4 //
5 // Library: librnr
6 //
7 // File: opts.c
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2014-12-06 13:48:30 -0700 (Sat, 06 Dec 2014) $
12  * $Rev: 3823 $
13  *
14  * \brief Standard command-line options built-in options parsing and
15  * validation definitions.
16  *
17  * \author Robin Knight (robin.knight@roadnarrows.com)
18  *
19  * \pkgcopyright{2005-2018,RoadNarrows LLC.,http://www.roadnarrows.com}
20  */
21 // Permission is hereby granted, without written agreement and without
22 // license or royalty fees, to use, copy, modify, and distribute this
23 // software and its documentation for any purpose, provided that
24 // (1) The above copyright notice and the following two paragraphs
25 // appear in all copies of the source code and (2) redistributions
26 // including binaries reproduces these notices in the supporting
27 // documentation. Substantial modifications to this software may be
28 // copyrighted by their authors and need not follow the licensing terms
29 // described here, provided that the new terms are clearly indicated in
30 // all files where they apply.
31 //
32 // IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
33 // OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
34 // PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
35 // DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
36 // EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
37 // THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
40 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
41 // FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
42 // "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
43 // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
44 //
45 ////////////////////////////////////////////////////////////////////////////////
46 
47 #include <stdio.h>
48 #include <errno.h>
49 #include <getopt.h>
50 #include <stdlib.h>
51 #include <stdarg.h>
52 #include <libgen.h>
53 #include <limits.h>
54 #include <string.h>
55 
56 #include "rnr/rnrconfig.h"
57 #include "rnr/pkg.h"
58 #include "rnr/new.h"
59 #include "rnr/assoc.h"
60 #include "rnr/log.h"
61 
62 #include "rnr/opts.h"
63 
64 // ---------------------------------------------------------------------------
65 // Private Interface
66 // ---------------------------------------------------------------------------
67 
68 #ifdef LOG
69 /*!
70  * Name-Value Pair table of names to log levels.
71  */
73 {
74  {"nosym", -1},
75  {"off", LOG_LEVEL_OFF},
76  {"error", LOG_LEVEL_ERROR},
77  {"diag1", LOG_LEVEL_DIAG1},
78  {"diag2", LOG_LEVEL_DIAG2},
79  {"diag3", LOG_LEVEL_DIAG3},
80  {"diag4", LOG_LEVEL_DIAG4},
81  {"diag5", LOG_LEVEL_DIAG5}
82 };
83 #endif // LOG
84 
85 //
86 // RN logging modifier options.
87 //
88 #define OPTS_LONGOPT_LOG "log" ///< log long option name
89 #define OPTS_LONGOPT_LOGFILE "logfile" ///< log file long option name
90 #define OPTS_LONGOPT_LOGNOCOLOR "log-no-color" ///< log with no color option
91 #define OPTS_LONGOPT_LOGNOTIME "log-no-timestamp" ///< log no timestamps option
92 
93 /*!
94  * Internal options control structure
95  */
96 typedef struct
97 {
98  struct option *m_pLongOpts; ///< long options structure
99  char *m_sShortOpts; ///< short options string
100 } OptsCtl_T;
101 
102 /*!
103  * Built-in logging option working variables.
104  */
105 static int OptsLogLevel = LOG_LEVEL_DFT; ///< working log level value
106 static char *OptsLogFile = LOG_FILENAME_DFT; ///< working log file value
107 static bool_t OptsLogNoColor = false; ///< working log no color value
108 static bool_t OptsLogNoTimestamp = false; ///< working log no timestamp value
109 
110 /*!
111  * \brief Built-In Options
112  */
114 {
115 #ifdef LOG
116  // -l, --log <level>
117  {
119  .short_opt = 'l',
120  .has_arg = required_argument,
121  .has_default= true,
122  .opt_addr = &OptsLogLevel,
123  .fn_fmt = OptsFmtLogLevel,
124  .arg_name = "<level>",
125  .opt_desc =
126  "Set logging threshold level. All logging events with priority "
127  "<= %A will be "
128  "logged. All others will be ignored. Error events are always logged.\n"
129  "%A is one of:\n"
130  " 'off' or 0 - Disable all logging.\n"
131  " 'error' or 1 - Enable error and warning logging.\n"
132  " 'diag1' or 2 - Enable diagnostics 1 logging.\n"
133  " 'diag2' or 3 - Enable diagnostics 2 logging.\n"
134  " 'diag3' or 4 - Enable diagnostics 3 logging.\n"
135  " 'diag4' or 5 - Enable diagnostics 4 logging.\n"
136  " 'diag5' or 6 - Enable diagnostics 5 logging.\n"
137  " >6 - Enable user-defined logging.",
138  .pvt_retval = OPTS_RVAL_LOG
139  },
140 
141  // --logfile <file>
142  {
143  .long_opt = OPTS_LONGOPT_LOGFILE,
144  .short_opt = OPTS_NO_SHORT,
145  .has_arg = required_argument,
146  .has_default= true,
147  .opt_addr = &OptsLogFile,
148  .fn_fmt = OptsFmtStr,
149  .arg_name = "<file>",
150  .opt_desc =
151  "Set log file %A.\n"
152  "Special %A names:\n"
153  " '" LOG_FILENAME_STDERR "' - log to standard error.\n"
154  " '" LOG_FILENAME_STDOUT "' - log to standard output.",
155  .pvt_retval = OPTS_RVAL_LOGFILE
156  },
157 
158  // --log-no-color
159  {
160  .long_opt = OPTS_LONGOPT_LOGNOCOLOR,
161  .short_opt = OPTS_NO_SHORT,
162  .has_arg = no_argument,
163  .has_default= true,
164  .opt_addr = &OptsLogNoColor,
165  .fn_fmt = OptsFmtBool,
166  .arg_name = NULL,
167  .opt_desc =
168  "Disable logging with compiled ANSI color strings.",
169  .pvt_retval = OPTS_RVAL_LOGNOCOLOR
170  },
171 
172  // --log-no-timestamp
173  {
174  .long_opt = OPTS_LONGOPT_LOGNOTIME,
175  .short_opt = OPTS_NO_SHORT,
176  .has_arg = no_argument,
177  .has_default= true,
178  .opt_addr = &OptsLogNoTimestamp,
179  .fn_fmt = OptsFmtBool,
180  .arg_name = NULL,
181  .opt_desc =
182  "Disable logging with timestamps.",
183  .pvt_retval = OPTS_RVAL_LOGNOTIME
184  },
185 #endif // LOG
186 
187  // --help option
188  {
189  .long_opt = "help",
190  .short_opt = OPTS_NO_SHORT,
191  .has_arg = no_argument,
192  .opt_desc = "Display this help and exit.",
193  .pvt_retval = OPTS_RVAL_HELP
194  },
195 
196  // --version option
197  {
198  .long_opt = "version",
199  .short_opt = OPTS_NO_SHORT,
200  .has_arg = no_argument,
201  .opt_desc = "Output version information and exit.",
202  .pvt_retval = OPTS_RVAL_VERSION
203  },
204 
205  // null entry
206  {NULL, }
207 };
208 
209 
210 /*!
211  * \brief Reset argc,argv to start of non-option command arguments.
212  * \param optind Last option index.
213  * \param argc Argument count.
214  * \param argv Argument vector.
215  */
216 #define OPTS_RESET_ARGCV(optind, argc, argv) \
217  { argc -= optind; argv += optind; }
218 
219 #define MAX_FMT_BUF ((size_t)1024) ///< Format buffer size
220 
221 /*!
222  * PrettyPrint formats
223  */
224 #define HELP_OPT_OVER 30 ///< opt help desc 1st line indent
225 #define HELP_OPT_OVER_2 (HELP_OPT_OVER+2) ///< opt help desc 2nd line+ indent
226 #define HELP_MAX_COL 79 ///< max help column
227 
228 /*!
229  * \brief Indents (spaces) over, returning number of added indentation
230  * \param over Number of spaces.
231  */
232 inline int HelpIndent(int over) { return printf("%*s", over, ""); }
233 
234 /*!
235  * \brief Puts help newline, returning new output column position.
236  * \param over Number of spaces.
237  */
238 inline int HelpPutNL(int over) { printf("\n"); return HelpIndent(over); }
239 
240 /*!
241  * \brief Puts help buffer, returning new output column position
242  *
243  * \param col Current column position.
244  * \param colstart Column to start.
245  * \param buf Buffer to output.
246  * \param pbuflen [out] Buffer length.
247  *
248  * \return New column position.
249  */
250 static int HelpPutBuf(int col, int colstart, char buf[], size_t *pbuflen)
251 {
252  if( *pbuflen == 0 )
253  {
254  return col;
255  }
256  if( (col > colstart) && (col >= (HELP_MAX_COL - *pbuflen)) )
257  {
258  col = HelpPutNL(colstart);
259  }
260  buf[*pbuflen] = 0;
261  col += printf("%s", buf);
262  *pbuflen = 0;
263  return col;
264 }
265 
266 /*!
267  * \brief Puts help string, returning new output column position
268  *
269  * \param col Current column position.
270  * \param colstart Column to start.
271  * \param s Help string.
272  *
273  * \return New column position.
274  */
275 static int HelpPutStr(int col, int colstart, const char *s)
276 {
277  int n;
278 
279  if( (s == NULL) || (*s == 0) )
280  {
281  return col;
282  }
283  n = (int)strlen(s);
284  if( (col > colstart) && (col >= (HELP_MAX_COL - n)) )
285  {
286  col = HelpPutNL(colstart);
287  }
288  col += printf("%s", s);
289  return col;
290 }
291 
292 /*!
293  * \brief Puts help character, returning new output column position
294  *
295  * \param col Current column position.
296  * \param colstart Column to start.
297  * \param c Help character.
298  *
299  * \return New column position.
300  */
301 static int HelpPutC(int col, int colstart, int c)
302 {
303  if( col > HELP_MAX_COL )
304  {
305  col = HelpPutNL(colstart);
306  }
307  col += printf("%c", c);
308  return col;
309 }
310 
311 /*!
312  * \brief Gets help character into local buffer, returning new/same output
313  * column position
314  *
315  * \param col Current column position.
316  * \param colstart Column to start.
317  * \param buf [out] Buffer to put.
318  * \param bufsiz Buffer maximum size.
319  * \param pbuflen [out] Buffer insert point.
320  * \param c Help character to get (put into buffer).
321  *
322  * \return New column position.
323  */
324 static int HelpGetC(int col, int colstart, char buf[], size_t bufsiz,
325  size_t *pbuflen, int c)
326 {
327  if( *pbuflen >= bufsiz )
328  {
329  *pbuflen = bufsiz - 1;
330  col = HelpPutBuf(col, colstart, buf, pbuflen);
331  }
332  else
333  {
334  buf[*pbuflen] = (char)c;
335  *pbuflen += 1;
336  }
337  return col;
338 }
339 
340 /*!
341  * \brief Prints formatted description.
342  *
343  * \par Formatting Directives:
344  * The description argumnet sFmtDesc may contain the following formatting
345  * directives:\n
346  * \b %P - print program name (argv0)\n
347  * \b %L - print name of Long argument\n
348  * \b %S - print name of Short argument\n
349  * \b %A - print name of option Argument\n
350  * \b %D - print value of Default\n
351  * \b %% - print %
352  *
353  *
354  * \param col Current column position.
355  * \param colstart Column to start.
356  * \param sFmtDesc Formatted description string.
357  * \param sPgmName Program name (argv0).
358  * \param pOptsInfo Options info.
359  *
360  * \return New column position.
361  */
362 static int OptsPrintf(int col,
363  int colstart,
364  const char *sFmtDesc,
365  const char *sPgmName,
366  OptsInfo_T *pOptsInfo)
367 {
368  char buf[1028];
369  size_t buflen = 0;
370  const char *s;
371 
372  for(s=sFmtDesc; s && *s; ++s)
373  {
374  switch( *s )
375  {
376  case '\n':
377  col = HelpPutBuf(col, colstart, buf, &buflen);
378  col = HelpPutNL(colstart);
379  break;
380  case ' ':
381  case '\t':
382  col = HelpPutBuf(col, colstart, buf, &buflen);
383  col = HelpPutC(col, colstart, ' ');
384  break;
385  case '%':
386  ++s;
387  switch(*s)
388  {
389  case 'P':
390  if( sPgmName != NULL )
391  {
392  col = HelpPutBuf(col, colstart, buf, &buflen);
393  col = HelpPutStr(col, colstart, sPgmName);
394  }
395  break;
396  case 'L':
397  if((pOptsInfo != NULL) && (pOptsInfo->long_opt != NULL))
398  {
399  col = HelpPutBuf(col, colstart, buf, &buflen);
400  col = HelpPutStr(col, colstart, pOptsInfo->long_opt);
401  }
402  break;
403  case 'S':
404  if((pOptsInfo != NULL) && (pOptsInfo->short_opt != OPTS_NO_SHORT))
405  {
406  col = HelpGetC(col, colstart, buf, sizeof(buf), &buflen,
407  pOptsInfo->short_opt);
408  }
409  break;
410  case 'A':
411  if((pOptsInfo != NULL) && (pOptsInfo->arg_name != NULL))
412  {
413  col = HelpPutBuf(col, colstart, buf, &buflen);
414  col = HelpPutStr(col, colstart, pOptsInfo->arg_name);
415  }
416  break;
417  case 'D':
418  if((pOptsInfo != NULL) && (pOptsInfo->pvt_opt_dft != NULL))
419  {
420  col = HelpPutBuf(col, colstart, buf, &buflen);
421  col = HelpPutStr(col, colstart, pOptsInfo->pvt_opt_dft);
422  }
423  break;
424  case '%':
425  col = HelpGetC(col, colstart, buf, sizeof(buf), &buflen, *s);
426  break;
427  default:
428  --s;
429  LOGERROR("Invalid print directive: '%.2s'", s);
430  break;
431  }
432  break;
433  default:
434  col = HelpGetC(col, colstart, buf, sizeof(buf), &buflen, *s);
435  break;
436  }
437  }
438 
439  // the last word
440  if( buflen > 0 )
441  {
442  col = HelpPutBuf(col, colstart, buf, &buflen);
443  }
444 
445  return col;
446 }
447 
448 /*!
449  * \brief Prints option syntax and description in standard 'usage' format.
450  *
451  * \param argv0 Program name.
452  * \param pOptsInfo Options info.
453  *
454  * \return New column position.
455  */
456 static void OptsPrintOpt(const char *argv0, OptsInfo_T *pOptsInfo)
457 {
458  char buf[1028], buf2[256];
459  size_t buflen = sizeof(buf), buflen2 = sizeof(buf2);
460  int col;
461 
462  // indent
463  col = snprintf(buf, buflen, " ");
464 
465  // short option
466  if( pOptsInfo->short_opt != OPTS_NO_SHORT )
467  {
468  col += snprintf(buf+col, buflen-(size_t)col, "-%c", pOptsInfo->short_opt);
469  }
470  else
471  {
472  col += snprintf(buf+col, buflen-(size_t)col, " ");
473  }
474 
475  // long option
476  if( pOptsInfo->long_opt != NULL )
477  {
478  col += snprintf(buf+col, buflen-(size_t)col, "%s--%s",
479  (pOptsInfo->short_opt != OPTS_NO_SHORT? ", ": " "),
480  pOptsInfo->long_opt);
481  }
482 
483  // option argument name
484  if( (pOptsInfo->has_arg != no_argument) &&
485  (pOptsInfo->arg_name != NULL) )
486  {
487  col += snprintf(buf+col, buflen-(size_t)col, "%s%s",
488  (pOptsInfo->long_opt != NULL? "=": " "),
489  pOptsInfo->arg_name);
490 
491  }
492 
493  // print option keyword(s) syntax
494  buf[sizeof(buf)-1] = 0;
495  printf("%s", buf);
496  buflen = 0;
497 
498  // scoot over to start of description column
499  if( col > HELP_OPT_OVER )
500  {
501  printf("\n");
502  col = 0;
503  }
505  col = HELP_OPT_OVER;
506 
507  // option default value string
508  if( pOptsInfo->has_default
509  && (pOptsInfo->fn_fmt != NULL)
510  && (pOptsInfo->opt_addr != NULL) )
511  {
512  pOptsInfo->pvt_opt_dft =
513  pOptsInfo->fn_fmt(buf2, buflen2, pOptsInfo->opt_addr);
514  }
515  else
516  {
517  pOptsInfo->pvt_opt_dft = NULL;
518  }
519 
520  // print description
521  col = OptsPrintf(col, HELP_OPT_OVER_2, pOptsInfo->opt_desc, argv0,
522  pOptsInfo);
523 
524  printf("\n");
525 
526  // print default value
527  if( pOptsInfo->pvt_opt_dft != NULL )
528  {
530  printf("DEFAULT: %s\n", pOptsInfo->pvt_opt_dft);
531  }
532 }
533 
534 /*!
535  * \brief Prints command-line help.
536  *
537  * This functions is called to act on --help option.
538  *
539  * \param argv0 Program name.
540  * \param pOptsInfo Options info.
541  * \param pPgmInfo Program info.
542  * \param bHasLogging This program does [not] support the logging optoins.
543  */
544 static void OptsHelp(const char *argv0,
545  OptsInfo_T *pOptsInfo,
546  OptsPgmInfo_T *pPgmInfo,
547  bool_t bHasLogging)
548 {
549  OptsInfo_T *p;
550  int col;
551 
552  // usage
553  col = printf("Usage: %s [OPTIONS] ", argv0);
554  if( (pPgmInfo != NULL) && (pPgmInfo->usage_args != NULL) )
555  {
556  col = OptsPrintf(col, 2, pPgmInfo->usage_args, argv0, NULL);
557  }
558 
559  // synopsis
560  printf("\n");
561  if( (pPgmInfo != NULL) && (pPgmInfo->synopsis != NULL) )
562  {
563  col = OptsPrintf(0, 0, pPgmInfo->synopsis, argv0, NULL);
564  printf("\n");
565  }
566 
567  // options
568  printf(
569 "\n"
570 "Mandatory arguments to long options are also mandatory for short options.\n");
571 
572  if( pOptsInfo != NULL )
573  {
574  for(p=pOptsInfo; p->long_opt!=NULL; ++p)
575  {
576  OptsPrintOpt(argv0, p);
577  }
578  }
579 
580  for(p=OptsBuiltIn; p->long_opt!=NULL; ++p)
581  {
582  if( !bHasLogging &&
583  ((p->pvt_retval == OPTS_RVAL_LOG)
584  || (p->pvt_retval == OPTS_RVAL_LOGFILE)) )
585  {
586  continue;
587  }
588  if( p->pvt_retval == OPTS_RVAL_HELP )
589  {
590  printf("\n");
591  }
592  OptsPrintOpt(argv0, p);
593  }
594 
595  // long description
596  if( (pPgmInfo != NULL) && (pPgmInfo->long_desc != NULL) )
597  {
598  printf("\n");
599  col = OptsPrintf(0, 0, pPgmInfo->long_desc, argv0, NULL);
600  printf("\n");
601  }
602 
603  // diagnostics
604  if( (pPgmInfo != NULL) && (pPgmInfo->diagnostics != NULL) )
605  {
606  printf("\n");
607  printf("DIAGNOSTICS:\n");
608  col = OptsPrintf(0, 0, pPgmInfo->diagnostics, argv0, NULL);
609  printf("\n");
610  }
611 }
612 
613 /*!
614  * \brief Prints command-line program version string(s).
615  *
616  * This functions is called to act on --version option.
617  *
618  * \param argv0 Program name.
619  * \param pPkgInfo Package info.
620  */
621 static void OptsVersion(const char *argv0, const PkgInfo_T *pPkgInfo)
622 {
623  printf(
624 "%s (package %s-%s %s)\n"
625 "Written by %s\n\n"
626 "Copyright (C) %s %s\n"
627 "%s\n",
628  argv0,
629  pPkgInfo->m_sPkgName, pPkgInfo->m_sPkgVersion, pPkgInfo->m_sPkgTimeStamp,
630  pPkgInfo->m_sPkgAuthors,
631  pPkgInfo->m_sPkgDate, pPkgInfo->m_sPkgOwners,
632  pPkgInfo->m_sPkgDisclaimer);
633 }
634 
635 /*!
636  * \brief Set program logging level.
637  *
638  * This function is called to act on the --log <level> option.
639  *
640  * \param argv0 Program name.
641  * \param sOptName Long option name.
642  * \param optarg Long option argument (from getopt_long(3)).
643  */
644 static void OptsLogSetLevel(const char *argv0, const char *sOptName,
645  char *optarg)
646 {
647 #ifdef LOG
648  int level;
649 
650  OptsCvtArgLogLevel(argv0, sOptName, optarg, &level);
651  LOG_SET_THRESHOLD(level);
652 #endif // LOG
653 }
654 
655 /*!
656  * \brief Set program logging output file.
657  *
658  * This function is called to act on the --logfile <file> option.
659  *
660  * \param argv0 Program name.
661  * \param sOptName Long option name.
662  * \param optarg Long option argument (from getopt_long(3)).
663  */
664 static void OptsLogSetFile(const char *argv0, const char *sOptName,
665  char *optarg)
666 {
667 #ifdef LOG
668  char *sFileName;
669 
670  OptsCvtArgStr(argv0, sOptName, optarg, &sFileName);
671  LOG_SET_LOGFILE(sFileName);
672 #endif // LOG
673 }
674 
675 /*!
676  * \brief Disable program logging in color.
677  *
678  * This function is called to act on the --log-no-color option.
679  *
680  * \param argv0 Program name.
681  * \param sOptName Long option name.
682  * \param optarg Long option argument (from getopt_long(3)).
683  */
684 static void OptsLogDisableColor(const char *argv0, const char *sOptName,
685  char *optarg)
686 {
687 #ifdef LOG
688  LOG_SET_COLOR_ENABLE(false);
689 #endif // LOG
690 }
691 
692 
693 /*!
694  * \brief Disable program logging with timestamps.
695  *
696  * This function is called to act on the --log-no-timestamp option.
697  *
698  * \param argv0 Program name.
699  * \param sOptName Long option name.
700  * \param optarg Long option argument (from getopt_long(3)).
701  */
702 static void OptsLogDisableTimestamp(const char *argv0, const char *sOptName,
703  char *optarg)
704 {
705 #ifdef LOG
707 #endif // LOG
708 }
709 /*!
710  * \brief Allocate and build short and long options getopt_long() parameters
711  * from the provided option info.
712  *
713  * \param pOptsInfo Options info table.
714  * \param bHasLogging This program does [not] support the logging optoins.
715  *
716  * \return New options control structure.
717  */
718 static OptsCtl_T *OptsNew(OptsInfo_T *pOptsInfo, bool_t bHasLogging)
719 {
720  size_t n;
721  struct option *pLongOpts, *p;
722  OptsInfo_T *q;
723  char *sShortOpts, *s;
724  OptsCtl_T *pOptsCtl;
725 
726  // count the number of options
727  for(n=0; pOptsInfo[n].long_opt!=NULL; ++n); // user
728 
729  n += arraysize(OptsBuiltIn) - 1;
730 
731  // allocate memory
732  pLongOpts = new(sizeof(struct option)*(n+1)); // include null
733  sShortOpts = new(sizeof(char)*(n*3+1)); // include null
734 
735  //
736  // Make Built-In long and short option arguments to getopt_long()
737  //
738  for(p=pLongOpts, s=sShortOpts, q=OptsBuiltIn; q->long_opt!=NULL; ++q)
739  {
740  // ignore logging options
741  if( !bHasLogging
742  && (!strcmp(q->long_opt, OPTS_LONGOPT_LOG)
743  || !strcmp(q->long_opt, OPTS_LONGOPT_LOGFILE)) )
744  {
745  continue;
746  }
747 
748  // long option also has corresponding short option
749  if( q->short_opt != OPTS_NO_SHORT )
750  {
751  *s++ = (char)(q->short_opt);
752  if( q->has_arg != no_argument )
753  {
754  *s++ = ':';
755  }
756  if( q->has_arg == optional_argument )
757  {
758  *s++ = ':';
759  }
760 
761  // check return value must be an ascii characater
762  if( q->pvt_retval != q->short_opt )
763  {
764  fprintf(stderr,
765  "Warning: Built-in option pvt_retval 0x%x != short_opt '%c'\n",
766  q->pvt_retval, q->short_opt);
767  }
768  }
769 
770  // long option
771  p->name = q->long_opt;
772  p->has_arg = q->has_arg;
773  p->flag = NULL;
774  p->val = q->pvt_retval;
775  p++;
776  }
777 
778  //
779  // Make User-Defined long and short option arguments to getopt_long()
780  //
781  for(n=0, q=pOptsInfo; q->long_opt!=NULL; ++n, ++q)
782  {
783  // long option only
784  if( q->short_opt == OPTS_NO_SHORT )
785  {
786  q->pvt_retval = OPTS_RVAL_USER + (int)n;
787  }
788  // long option also has corresponding short option
789  else
790  {
791  *s++ = (char)(q->short_opt);
792  if( q->has_arg != no_argument )
793  {
794  *s++ = ':';
795  }
796  if( q->has_arg == optional_argument )
797  {
798  *s++ = ':';
799  }
800  q->pvt_retval = q->short_opt;
801  }
802 
803  // long option
804  p->name = q->long_opt;
805  p->has_arg = q->has_arg;
806  p->flag = NULL;
807  p->val = q->pvt_retval;
808  p++;
809  }
810 
811  // end of long options
812  p->name = NULL;
813  p->has_arg = no_argument;
814  p->flag = NULL;
815  p->val = 0;
816 
817  // end of short options string
818  *s = 0;
819 
820  pOptsCtl = NEW(OptsCtl_T);
821  pOptsCtl->m_pLongOpts = pLongOpts;
822  pOptsCtl->m_sShortOpts = sShortOpts;
823 
824  return pOptsCtl;
825 }
826 
827 /*!
828  * \brief Delete an allocated options control structure.
829  *
830  * \param pOptsCtl Options control structure.
831  */
832 static void OptsDelete(OptsCtl_T *pOptsCtl)
833 {
834  if( pOptsCtl != NULL )
835  {
836  delete(pOptsCtl->m_pLongOpts);
837  delete(pOptsCtl->m_sShortOpts);
838  delete(pOptsCtl);
839  }
840 }
841 
842 // ---------------------------------------------------------------------------
843 // Public Interface
844 // ---------------------------------------------------------------------------
845 
846 /*!
847  * \brief Gets, validates, and sets all command line options.
848  *
849  * \param argv0 (Massaged) program name.
850  * \param pPkgInfo Package info.
851  * \param pPgmInfo Program info.
852  * \param pOptsInfo Program options info.
853  * \param bHasLogging Do [not] include logging options.
854  * \param[out] pargc New non-option argument count.
855  * \param argv Command-line options and arguments.
856  * arguments.
857  *
858  * \return Reposition command-line arguments to start of first non-option
859  * comand argument.
860  */
861 char **OptsGet(const char *argv0,
862  const PkgInfo_T *pPkgInfo,
863  OptsPgmInfo_T *pPgmInfo,
864  OptsInfo_T *pOptsInfo,
865  bool_t bHasLogging,
866  int *pargc, char *argv[])
867 {
868  OptsCtl_T *pOptsCtl;
869  OptsInfo_T *p;
870  int argc = *pargc;
871  int c;
872  int option_index;
873  bool_t bHasOpt;
874 
875  //
876  // Set external getopt_long() variables. N.B. makes OptsGet() non-reentrant.
877  //
878  optarg = NULL; // current argument to option
879  optind = 0; // next index in argv to look for options
880  opterr = 1; // allow getopt_long() to print error messages
881  optopt = 0; // current parsed option character
882 
883  // build option arguments from info
884  pOptsCtl = OptsNew(pOptsInfo, bHasLogging);
885 
886  // parse and convert options
887  while(true)
888  {
889  option_index = 0;
890 
891  // parse next long/short option
892  c = getopt_long(argc, argv, pOptsCtl->m_sShortOpts, pOptsCtl->m_pLongOpts,
893  &option_index);
894 
895  // end of option list
896  if( c == -1 )
897  {
898  break;
899  }
900 
901  // process option
902  switch(c)
903  {
904  case OPTS_RVAL_ERROR: // -? options error
905  OptsInvalid(argv0, "");
906  break;
907  case OPTS_RVAL_HELP: // --help
908  OptsHelp(argv0, pOptsInfo, pPgmInfo, bHasLogging);
909  exit(OK);
910  break;
911  case OPTS_RVAL_VERSION: // --version
912  OptsVersion(argv0, pPkgInfo);
913  exit(OK);
914  break;
915  case OPTS_RVAL_LOG: // -l, --log <level>
916  OptsLogSetLevel(argv0, OPTS_LONGOPT_LOG, optarg);
917  break;
918  case OPTS_RVAL_LOGFILE: // --logfile <file>
919  OptsLogSetFile(argv0, OPTS_LONGOPT_LOGFILE, optarg);
920  break;
921  case OPTS_RVAL_LOGNOCOLOR: // --log-no-color
922  OptsLogDisableColor(argv0, OPTS_LONGOPT_LOG, optarg);
923  break;
924  case OPTS_RVAL_LOGNOTIME: // --log-no-timestamp
926  break;
927  default: // user application option
928  bHasOpt = false;
929  for(p=pOptsInfo; (p!=NULL) && (p->long_opt!=NULL); ++p)
930  {
931  if( p->pvt_retval == c )
932  {
933  bHasOpt = true;
934 
935  // user supplied option conversion function
936  if( p->fn_cvt != NULL )
937  {
938  p->fn_cvt(argv0, p->long_opt, optarg, p->opt_addr);
939  }
940  // default for option w/o argument is boolean true value
941  else if( p->has_arg == no_argument )
942  {
943  *((int *)p->opt_addr) = true;
944  }
945  // default for option w/ argument is string value
946  else
947  {
948  OptsCvtArgStr(argv0, p->long_opt, optarg, p->opt_addr);
949  }
950  }
951  }
952  if( !bHasOpt )
953  {
954  fprintf(stderr, "Warning: getopt_long() return character code 0x%x\n",
955  c);
956  exit(EC_BAD_OPT);
957  }
958  break;
959  }
960  }
961 
962  OptsDelete(pOptsCtl);
963 
964  OPTS_RESET_ARGCV(optind, argc, argv);
965 
966  *pargc = argc;
967 
968  return argv;
969 }
970 
971 /*!
972  * \brief Convert options string argument to string.
973  *
974  * \note Function returns integer for derived applications. librnr Opts
975  * ignores the return value.
976  *
977  * \param argv0 Command name.
978  * \param sOptName Option name.
979  * \param optarg Parsed option argument to convert (optional).
980  * \param[out] pOptVal Pointer to converted option value.
981  *
982  * \par Default:
983  * \p "" (zero-length string)
984  *
985  * \return If returns, then returns OK.
986  */
987 int OptsCvtArgStr(const char *argv0, const char *sOptName, char *optarg,
988  void *pOptVal)
989 {
990  *((char **)pOptVal) = new_strdup(optarg);
991  return OK;
992 }
993 
994 //
995 // Convert options boolean argument to bool
996 //
997 /*!
998  * \brief Convert options boolean argument to bool_t.
999  *
1000  * 1 or "true" converts to \p true.
1001  * \n 0 or "false" converts to \p false.
1002  *
1003  * \note Function returns integer for derived applications. librnr Opts
1004  * ignores the return value.
1005  *
1006  * \param argv0 Command name.
1007  * \param sOptName Option name.
1008  * \param optarg Parsed option argument to convert (optional).
1009  * \param[out] pOptVal Pointer to converted option value.
1010  *
1011  * \par Default:
1012  * \p true
1013  *
1014  * \exception OPTSBADARG()
1015  *
1016  * \return If returns, then returns OK.
1017  */
1018 int OptsCvtArgBool(const char *argv0, const char *sOptName, char *optarg,
1019  void *pOptVal)
1020 {
1021  if( optarg )
1022  {
1023  if( !strcmp(optarg, "true") || !strcmp(optarg, "1") )
1024  {
1025  *((bool_t *)pOptVal) = true;
1026  }
1027  else if( !strcmp(optarg, "false") || !strcmp(optarg, "0") )
1028  {
1029  *((bool_t *)pOptVal) = false;
1030  }
1031  else
1032  {
1033  OPTSBADARG(argv0, sOptName, optarg);
1034  }
1035  }
1036  // optional argument default
1037  else
1038  {
1039  *((bool_t *)pOptVal) = true;
1040  }
1041 
1042  return OK;
1043 }
1044 
1045 /*!
1046  * \brief Convert options integer argument to integer.
1047  *
1048  * Accepted formats: decimal hexidecimal(0x<hexdigits>) octal(0<octaldigits>).
1049  *
1050  * \note Function returns integer for derived applications. librnr Opts
1051  * ignores the return value.
1052  *
1053  * \param argv0 Command name.
1054  * \param sOptName Option name.
1055  * \param optarg Parsed option argument to convert (optional).
1056  * \param[out] pOptVal Pointer to converted option value.
1057  *
1058  * \par Default:
1059  * \p 1
1060  *
1061  * \exception OPTSBADARG()
1062  *
1063  * \return If returns, then returns OK.
1064  */
1065 int OptsCvtArgInt(const char *argv0, const char *sOptName, char *optarg,
1066  void *pOptVal)
1067 {
1068  int optargInt;
1069  char *optargEnd;
1070 
1071  if( optarg )
1072  {
1073  optargInt = (int)strtol(optarg, &optargEnd, 0);
1074  if( *optargEnd != 0 )
1075  {
1076  OPTSBADARG(argv0, sOptName, optarg);
1077  }
1078  *((int *)pOptVal) = optargInt;
1079  }
1080  // optional argument default
1081  else
1082  {
1083  *((int *)pOptVal) = 1;
1084  }
1085 
1086  return OK;
1087 }
1088 
1089 /*!
1090  * \brief Convert options float argument to double.
1091  *
1092  * Accepted format: optionally signed floating-point number.
1093  *
1094  * \note Function returns integer for derived applications. librnr Opts
1095  * ignores the return value.
1096  *
1097  * \param argv0 Command name.
1098  * \param sOptName Option name.
1099  * \param optarg Parsed option argument to convert (optional).
1100  * \param[out] pOptVal Pointer to converted option value.
1101  *
1102  * \par Default:
1103  * \p 1.0
1104  *
1105  * \exception OPTSBADARG()
1106  *
1107  * \return If returns, then returns OK.
1108  */
1109 int OptsCvtArgFloat(const char *argv0, const char *sOptName, char *optarg,
1110  void *pOptVal)
1111 {
1112  double optargFloat;
1113 
1114  if( optarg )
1115  {
1116  if( sscanf(optarg, "%lf", &optargFloat) != 1 )
1117  {
1118  OPTSBADARG(argv0, sOptName, optarg);
1119  }
1120  *((double *)pOptVal) = optargFloat;
1121  }
1122  // optional argument default
1123  else
1124  {
1125  *((double *)pOptVal) = 1.0;
1126  }
1127 
1128  return OK;
1129 }
1130 
1131 /*!
1132  * \brief Convert options string argument to log threshold level.
1133  *
1134  * Format: "off", "error", "diag1", "diag2", "diag3", "diag4", "diag5", or >= 0
1135  *
1136  * \note Function returns integer for derived applications. librnr Opts
1137  * ignores the return value.
1138  *
1139  * \param argv0 Command name.
1140  * \param sOptName Option name.
1141  * \param optarg Parsed option argument to convert (optional).
1142  * \param[out] pOptVal Pointer to converted option value.
1143  *
1144  * \par Default:
1145  * \p LOG_LEVEL_DFT
1146  *
1147  * \exception OPTSBADARG()
1148  *
1149  * \return If returns, then returns OK.
1150  */
1151 int OptsCvtArgLogLevel(const char *argv0, const char *sOptName, char *optarg,
1152  void *pOptVal)
1153 {
1154  int logLevel;
1155 
1156  if( optarg )
1157  {
1158  logLevel = NvpName2Val(OptsLogLevelTbl, arraysize(OptsLogLevelTbl), optarg);
1159 
1160  // assume integer format
1161  if( logLevel < LOG_LEVEL_OFF )
1162  {
1163  OptsCvtArgInt(argv0, sOptName, optarg, &logLevel);
1164  }
1165  }
1166  // optional argument default
1167  else
1168  {
1169  logLevel = LOG_LEVEL_DFT;
1170  }
1171 
1172  if( logLevel < LOG_LEVEL_OFF )
1173  {
1174  logLevel = LOG_LEVEL_OFF;
1175  }
1176 
1177  *((int *)pOptVal) = logLevel;
1178 
1179  return OK;
1180 }
1181 
1182 /*!
1183  * \brief String option value string formatter.
1184  *
1185  * \param[out] buf Output buffer.
1186  * \param buflen Buffer length.
1187  * \param pOptVal Option value.
1188  *
1189  * \return Pointer to start of buf.
1190  */
1191 char *OptsFmtStr(char *buf, size_t buflen, void *pOptVal)
1192 {
1193 
1194  if( (pOptVal == NULL) || (*((char **)pOptVal) == NULL) )
1195  {
1196  buf[0] = 0;
1197  }
1198  else
1199  {
1200  strncpy(buf, *((char **)pOptVal), buflen);
1201  buf[buflen-1] = 0;
1202  }
1203  return buf;
1204 }
1205 
1206 /*!
1207  * \brief Integer option value string formatter.
1208  *
1209  * \param[out] buf Output buffer.
1210  * \param buflen Buffer length.
1211  * \param pOptVal Option value.
1212  *
1213  * \return Pointer to start of buf.
1214  */
1215 char *OptsFmtInt(char *buf, size_t buflen, void *pOptVal)
1216 {
1217  snprintf(buf, buflen, "%d", *((int *)pOptVal));
1218  buf[buflen-1] = 0;
1219  return buf;
1220 }
1221 
1222 /*!
1223  * \brief Float option value string formatter.
1224  *
1225  * \param[out] buf Output buffer.
1226  * \param buflen Buffer length.
1227  * \param pOptVal Option value.
1228  *
1229  * \return Pointer to start of buf.
1230  */
1231 char *OptsFmtFloat(char *buf, size_t buflen, void *pOptVal)
1232 {
1233  snprintf(buf, buflen, "%f", *((double *)pOptVal));
1234  buf[buflen-1] = 0;
1235  return buf;
1236 }
1237 
1238 /*!
1239  * \brief Boolean option value string formatter.
1240  *
1241  * \param[out] buf Output buffer.
1242  * \param buflen Buffer length.
1243  * \param pOptVal Option value.
1244  *
1245  * \return Pointer to start of buf.
1246  */
1247 char *OptsFmtBool(char *buf, size_t buflen, void *pOptVal)
1248 {
1249  char *s;
1250 
1251  if( *((int *)pOptVal) == true )
1252  {
1253  s = "true";
1254  }
1255  else
1256  {
1257  s = "false";
1258  }
1259  strncpy(buf, s, buflen);
1260  buf[buflen-1] = 0;
1261  return buf;
1262 }
1263 
1264 /*!
1265  * \brief Character option value string formatter.
1266  *
1267  * \param[out] buf Output buffer.
1268  * \param buflen Buffer length.
1269  * \param pOptVal Option value.
1270  *
1271  * \return Pointer to start of buf.
1272  */
1273 char *OptsFmtChar(char *buf, size_t buflen, void *pOptVal)
1274 {
1275  buf[0] = *((char *)pOptVal);
1276  buf[1] = 0;
1277  return buf;
1278 }
1279 
1280 /*!
1281  * \brief Log Level option value string formatter.
1282  *
1283  * \param[out] buf Output buffer.
1284  * \param buflen Buffer length.
1285  * \param pOptVal Option value.
1286  *
1287  * \return Pointer to start of buf.
1288  */
1289 char *OptsFmtLogLevel(char *buf, size_t buflen, void *pOptVal)
1290 {
1291  int level = *((int *)pOptVal);
1292  char *off = "off";
1293 
1294  if( level == LOG_LEVEL_OFF )
1295  {
1296  return OptsFmtStr(buf, buflen, &off);
1297  }
1298  else
1299  {
1300  return OptsFmtInt(buf, buflen, pOptVal);
1301  }
1302 }
1303 
1304 /*!
1305  * \brief Invalid option or option argument print and exit.
1306  *
1307  * \param argv0 Program name.
1308  * \param sFmt Error format string.
1309  * \param ... Variable arguments to format string.
1310  *
1311  * \note The function terminates process with exit status \p EC_BAD_OPT(2).
1312  */
1313 void OptsInvalid(const char *argv0, const char *sFmt, ...)
1314 {
1315  va_list ap;
1316  char fmtbuf[MAX_FMT_BUF];
1317 
1318  if( (sFmt != NULL) && (*sFmt != 0) )
1319  {
1320  snprintf(fmtbuf, MAX_FMT_BUF, "%s: %s\n", argv0, sFmt);
1321  fmtbuf[MAX_FMT_BUF-1] = 0;
1322  va_start(ap, sFmt);
1323  vfprintf(stderr, fmtbuf, ap);
1324  va_end(ap);
1325  }
1326  fprintf(stderr, "Try '%s --help' for more information.\n", argv0);
1327  exit(EC_BAD_OPT);
1328 }
Simple associative map data and operator declarations.
char * OptsFmtBool(char *buf, size_t buflen, void *pOptVal)
Boolean option value string formatter.
Definition: opts.c:1247
void LOG_SET_TIMESTAMP_ENABLE(bool_t enable)
Enable/disable log timestamps.
Definition: log.c:176
static Nvp_T OptsLogLevelTbl[]
Definition: opts.c:72
int OptsCvtArgInt(const char *argv0, const char *sOptName, char *optarg, void *pOptVal)
Convert options integer argument to integer.
Definition: opts.c:1065
void LOG_SET_COLOR_ENABLE(bool_t enable)
Enable/disable logging in color.
Definition: log.c:160
const char * diagnostics
Programs diagnostics subsection string.
Definition: opts.h:254
static void OptsDelete(OptsCtl_T *pOptsCtl)
Delete an allocated options control structure.
Definition: opts.c:832
#define LOG_LEVEL_DIAG2
diagnostic level 2
Definition: log.h:182
#define LOG_LEVEL_OFF
turn off all non-error logging
Definition: log.h:179
char * m_sShortOpts
short options string
Definition: opts.c:99
#define OPTS_RVAL_LOGNOTIME
–log-no-timestamp rval
Definition: opts.h:111
int short_opt
Short option character.
Definition: opts.h:143
const char * m_sPkgVersion
package dotted version string
Definition: pkg.h:37
OptsFmtFunc_T fn_fmt
Option value string formatting function.
Definition: opts.h:177
char * new_strdup(const char *s)
Duplicate a string.
Definition: new.c:176
static void OptsLogDisableTimestamp(const char *argv0, const char *sOptName, char *optarg)
Disable program logging with timestamps.
Definition: opts.c:702
Standard command-line options options and parsing.
static int HelpPutC(int col, int colstart, int c)
Puts help character, returning new output column position.
Definition: opts.c:301
Program Description Strings Info Structure.
Definition: opts.h:226
int OptsCvtArgLogLevel(const char *argv0, const char *sOptName, char *optarg, void *pOptVal)
Convert options string argument to log threshold level.
Definition: opts.c:1151
#define OPTS_RVAL_USER
start of user available
Definition: opts.h:112
#define OK
Okay.
Definition: rnrconfig.h:301
#define LOG_LEVEL_DIAG5
diagnostic level 5
Definition: log.h:185
#define NULL
null pointer
Definition: rnrconfig.h:199
static bool_t OptsLogNoTimestamp
working log no timestamp value
Definition: opts.c:108
int LOG_SET_THRESHOLD(int nLevel)
Set new logging threshold level.
Definition: log.c:96
void * opt_addr
Address of option variable.
Definition: opts.h:162
int HelpIndent(int over)
Indents (spaces) over, returning number of added indentation.
Definition: opts.c:232
#define OPTS_LONGOPT_LOGFILE
log file long option name
Definition: opts.c:89
Memory allocation and deallocation declarations.
char * OptsFmtFloat(char *buf, size_t buflen, void *pOptVal)
Float option value string formatter.
Definition: opts.c:1231
static void OptsLogDisableColor(const char *argv0, const char *sOptName, char *optarg)
Disable program logging in color.
Definition: opts.c:684
int HelpPutNL(int over)
Puts help newline, returning new output column position.
Definition: opts.c:238
RoadNarrows Robotics standard package information.
const char * long_desc
Program full description string.
Definition: opts.h:247
#define EC_BAD_OPT
bad command line option exit code
Definition: rnrconfig.h:311
#define OPTS_RVAL_HELP
–help return value
Definition: opts.h:107
Definition: assoc.h:151
#define HELP_MAX_COL
max help column
Definition: opts.c:226
int LOG_SET_LOGFILE(const char *sLogFileName)
Set new logging output file.
Definition: log.c:199
const char * synopsis
Simple program synopsis string.
Definition: opts.h:240
char * pvt_opt_dft
Option default value in string format.
Definition: opts.h:212
char ** OptsGet(const char *argv0, const PkgInfo_T *pPkgInfo, OptsPgmInfo_T *pPgmInfo, OptsInfo_T *pOptsInfo, bool_t bHasLogging, int *pargc, char *argv[])
Gets, validates, and sets all command line options.
Definition: opts.c:861
#define OPTS_LONGOPT_LOGNOTIME
log no timestamps option
Definition: opts.c:91
#define arraysize(array)
array size, i.e. number of array entries
Definition: rnrconfig.h:259
const char * m_sPkgTimeStamp
package build date
Definition: pkg.h:38
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
static void OptsHelp(const char *argv0, OptsInfo_T *pOptsInfo, OptsPgmInfo_T *pPgmInfo, bool_t bHasLogging)
Prints command-line help.
Definition: opts.c:544
static int OptsLogLevel
working log level value
Definition: opts.c:105
const char * m_sPkgDate
package extended creation date string
Definition: pkg.h:39
static void OptsPrintOpt(const char *argv0, OptsInfo_T *pOptsInfo)
Prints option syntax and description in standard &#39;usage&#39; format.
Definition: opts.c:456
char * OptsFmtInt(char *buf, size_t buflen, void *pOptVal)
Integer option value string formatter.
Definition: opts.c:1215
Definition: pkg.h:34
static int OptsPrintf(int col, int colstart, const char *sFmtDesc, const char *sPgmName, OptsInfo_T *pOptsInfo)
Prints formatted description.
Definition: opts.c:362
static int HelpPutStr(int col, int colstart, const char *s)
Puts help string, returning new output column position.
Definition: opts.c:275
const char * m_sPkgName
package name string
Definition: pkg.h:36
static char * OptsLogFile
working log file value
Definition: opts.c:106
const char * usage_args
Single line description string of non-option arguments.
Definition: opts.h:233
#define LOG_FILENAME_STDOUT
&#39;stdout&#39; log filename
Definition: log.h:211
const char * arg_name
Option argument name string.
Definition: opts.h:183
#define OPTS_LONGOPT_LOGNOCOLOR
log with no color option
Definition: opts.c:90
#define NEW(T)
Allocate new type.
Definition: new.h:49
#define OPTS_NO_SHORT
no short option equivalent
Definition: opts.h:99
#define LOG_LEVEL_DIAG3
diagnostic level 3
Definition: log.h:183
#define OPTS_RVAL_LOGFILE
–logfile return value
Definition: opts.h:109
char * OptsFmtLogLevel(char *buf, size_t buflen, void *pOptVal)
Log Level option value string formatter.
Definition: opts.c:1289
OptsCvtFunc_T fn_cvt
Option conversion function.
Definition: opts.h:170
static int HelpPutBuf(int col, int colstart, char buf[], size_t *pbuflen)
Puts help buffer, returning new output column position.
Definition: opts.c:250
static void OptsLogSetFile(const char *argv0, const char *sOptName, char *optarg)
Set program logging output file.
Definition: opts.c:664
#define LOG_LEVEL_DFT
default log level is off
Definition: log.h:187
int pvt_retval
Return value.
Definition: opts.h:204
#define HELP_OPT_OVER
opt help desc 1st line indent
Definition: opts.c:224
int bool_t
"boolean" T/F
Definition: rnrconfig.h:187
RoadNarrows Robotics common configuration file.
int OptsCvtArgFloat(const char *argv0, const char *sOptName, char *optarg, void *pOptVal)
Convert options float argument to double.
Definition: opts.c:1109
int OptsCvtArgBool(const char *argv0, const char *sOptName, char *optarg, void *pOptVal)
Convert options boolean argument to bool_t.
Definition: opts.c:1018
static OptsCtl_T * OptsNew(OptsInfo_T *pOptsInfo, bool_t bHasLogging)
Allocate and build short and long options getopt_long() parameters from the provided option info...
Definition: opts.c:718
bool_t has_default
Option does [not] have a default value.
Definition: opts.h:155
#define OPTS_RVAL_LOGNOCOLOR
–log-no-color rval
Definition: opts.h:110
struct option * m_pLongOpts
long options structure
Definition: opts.c:98
#define LOG_LEVEL_DIAG1
diagnostic level 1
Definition: log.h:181
#define OPTS_RESET_ARGCV(optind, argc, argv)
Reset argc,argv to start of non-option command arguments.
Definition: opts.c:216
const char * m_sPkgDisclaimer
package disclaimer string
Definition: pkg.h:43
#define HELP_OPT_OVER_2
opt help desc 2nd line+ indent
Definition: opts.c:225
static int HelpGetC(int col, int colstart, char buf[], size_t bufsiz, size_t *pbuflen, int c)
Gets help character into local buffer, returning new/same output column position. ...
Definition: opts.c:324
static void OptsLogSetLevel(const char *argv0, const char *sOptName, char *optarg)
Set program logging level.
Definition: opts.c:644
#define OPTS_RVAL_ERROR
options error
Definition: opts.h:104
void OptsInvalid(const char *argv0, const char *sFmt,...)
Invalid option or option argument print and exit.
Definition: opts.c:1313
#define LOG_FILENAME_DFT
default log filename
Definition: log.h:212
int has_arg
Option does [not] have an argument of type.
Definition: opts.h:149
char * OptsFmtStr(char *buf, size_t buflen, void *pOptVal)
String option value string formatter.
Definition: opts.c:1191
static bool_t OptsLogNoColor
working log no color value
Definition: opts.c:107
#define OPTS_RVAL_VERSION
–version return value
Definition: opts.h:108
static void OptsVersion(const char *argv0, const PkgInfo_T *pPkgInfo)
Prints command-line program version string(s).
Definition: opts.c:621
const char * m_sPkgOwners
package owner(s) string
Definition: pkg.h:42
#define OPTS_RVAL_LOG
-l, –log return value
Definition: opts.h:105
Logger declarations.
#define LOG_LEVEL_ERROR
errors
Definition: log.h:180
int OptsCvtArgStr(const char *argv0, const char *sOptName, char *optarg, void *pOptVal)
Convert options string argument to string.
Definition: opts.c:987
const char * opt_desc
Option description string.
Definition: opts.h:195
const char * long_opt
Long option string name.
Definition: opts.h:137
#define LOG_FILENAME_STDERR
&#39;stderr&#39; log filename
Definition: log.h:210
const char * m_sPkgAuthors
package author(s) string
Definition: pkg.h:41
#define MAX_FMT_BUF
Format buffer size.
Definition: opts.c:219
#define LOG_LEVEL_DIAG4
diagnostic level 4
Definition: log.h:184
#define OPTS_LONGOPT_LOG
log long option name
Definition: opts.c:88
#define OPTSBADARG(argv0, opt, arg)
Standard bad option error message reporter.
Definition: opts.h:263
Short and Long Options Info.
Definition: opts.h:134
static OptsInfo_T OptsBuiltIn[]
Built-In Options.
Definition: opts.c:113
Definition: opts.c:96
char * OptsFmtChar(char *buf, size_t buflen, void *pOptVal)
Character option value string formatter.
Definition: opts.c:1273
int NvpName2Val(Nvp_T tbl[], size_t nTblEntries, const char *sName)
Get the value associated with the name.
Definition: assoc.c:64