helpers.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright 2011 Rusty Russell
  3. * Copyright 2011 Con Kolivas
  4. *
  5. * This program is free software; you can redistribute it and/or modify it under
  6. * the terms of the GNU General Public License as published by the Free Software
  7. * Foundation; either version 2 of the License, or (at your option) any later
  8. * version. See LICENSE for more details.
  9. */
  10. #include <ccan/opt/opt.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <errno.h>
  14. #include <stdio.h>
  15. #include "private.h"
  16. /* Upper bound to sprintf this simple type? Each 3 bits < 1 digit. */
  17. #define CHAR_SIZE(type) (((sizeof(type)*CHAR_BIT + 2) / 3) + 1)
  18. /* FIXME: asprintf module? */
  19. static char *arg_bad(const char *fmt, const char *arg)
  20. {
  21. char *str = malloc(strlen(fmt) + strlen(arg));
  22. sprintf(str, fmt, arg);
  23. return str;
  24. }
  25. char *opt_set_bool(bool *b)
  26. {
  27. *b = true;
  28. return NULL;
  29. }
  30. char *opt_set_invbool(bool *b)
  31. {
  32. *b = false;
  33. return NULL;
  34. }
  35. char *opt_set_bool_arg(const char *arg, bool *b)
  36. {
  37. if (!strcasecmp(arg, "yes") || !strcasecmp(arg, "true"))
  38. return opt_set_bool(b);
  39. if (!strcasecmp(arg, "no") || !strcasecmp(arg, "false"))
  40. return opt_set_invbool(b);
  41. return opt_invalid_argument(arg);
  42. }
  43. char *opt_set_invbool_arg(const char *arg, bool *b)
  44. {
  45. char *err = opt_set_bool_arg(arg, b);
  46. if (!err)
  47. *b = !*b;
  48. return err;
  49. }
  50. /* Set a char *. */
  51. char *opt_set_charp(const char *arg, char **p)
  52. {
  53. *p = (char *)arg;
  54. return NULL;
  55. }
  56. /* Set an integer value, various forms. Sets to 1 on arg == NULL. */
  57. char *opt_set_intval(const char *arg, int *i)
  58. {
  59. long l;
  60. char *err = opt_set_longval(arg, &l);
  61. if (err)
  62. return err;
  63. *i = l;
  64. /* Beware truncation... */
  65. if (*i != l)
  66. return arg_bad("value '%s' does not fit into an integer", arg);
  67. return err;
  68. }
  69. char *opt_set_floatval(const char *arg, float *f)
  70. {
  71. char *endp;
  72. errno = 0;
  73. *f = strtof(arg, &endp);
  74. if (*endp || !arg[0])
  75. return arg_bad("'%s' is not a number", arg);
  76. if (errno)
  77. return arg_bad("'%s' is out of range", arg);
  78. return NULL;
  79. }
  80. char *opt_set_uintval(const char *arg, unsigned int *ui)
  81. {
  82. int i;
  83. char *err = opt_set_intval(arg, &i);
  84. if (err)
  85. return err;
  86. if (i < 0)
  87. return arg_bad("'%s' is negative", arg);
  88. *ui = i;
  89. return NULL;
  90. }
  91. char *opt_set_longval(const char *arg, long *l)
  92. {
  93. char *endp;
  94. /* This is how the manpage says to do it. Yech. */
  95. errno = 0;
  96. *l = strtol(arg, &endp, 0);
  97. if (*endp || !arg[0])
  98. return arg_bad("'%s' is not a number", arg);
  99. if (errno)
  100. return arg_bad("'%s' is out of range", arg);
  101. return NULL;
  102. }
  103. char *opt_set_ulongval(const char *arg, unsigned long *ul)
  104. {
  105. long int l;
  106. char *err;
  107. err = opt_set_longval(arg, &l);
  108. if (err)
  109. return err;
  110. *ul = l;
  111. if (l < 0)
  112. return arg_bad("'%s' is negative", arg);
  113. return NULL;
  114. }
  115. char *opt_inc_intval(int *i)
  116. {
  117. (*i)++;
  118. return NULL;
  119. }
  120. /* Display version string. */
  121. char *opt_version_and_exit(const char *version)
  122. {
  123. printf("%s\n", version);
  124. fflush(stdout);
  125. exit(0);
  126. }
  127. char *opt_usage_and_exit(const char *extra)
  128. {
  129. printf("%s", opt_usage(opt_argv0, extra));
  130. fflush(stdout);
  131. exit(0);
  132. }
  133. void opt_show_bool(char buf[OPT_SHOW_LEN], const bool *b)
  134. {
  135. strncpy(buf, *b ? "true" : "false", OPT_SHOW_LEN);
  136. }
  137. void opt_show_invbool(char buf[OPT_SHOW_LEN], const bool *b)
  138. {
  139. strncpy(buf, *b ? "false" : "true", OPT_SHOW_LEN);
  140. }
  141. void opt_show_charp(char buf[OPT_SHOW_LEN], char *const *p)
  142. {
  143. size_t len = strlen(*p);
  144. buf[0] = '"';
  145. if (len > OPT_SHOW_LEN - 2)
  146. len = OPT_SHOW_LEN - 2;
  147. strncpy(buf+1, *p, len);
  148. buf[1+len] = '"';
  149. if (len < OPT_SHOW_LEN - 2)
  150. buf[2+len] = '\0';
  151. }
  152. /* Set an integer value, various forms. Sets to 1 on arg == NULL. */
  153. void opt_show_intval(char buf[OPT_SHOW_LEN], const int *i)
  154. {
  155. snprintf(buf, OPT_SHOW_LEN, "%i", *i);
  156. }
  157. void opt_show_floatval(char buf[OPT_SHOW_LEN], const float *f)
  158. {
  159. snprintf(buf, OPT_SHOW_LEN, "%.1f", *f);
  160. }
  161. void opt_show_uintval(char buf[OPT_SHOW_LEN], const unsigned int *ui)
  162. {
  163. snprintf(buf, OPT_SHOW_LEN, "%u", *ui);
  164. }
  165. void opt_show_longval(char buf[OPT_SHOW_LEN], const long *l)
  166. {
  167. snprintf(buf, OPT_SHOW_LEN, "%li", *l);
  168. }
  169. void opt_show_ulongval(char buf[OPT_SHOW_LEN], const unsigned long *ul)
  170. {
  171. snprintf(buf, OPT_SHOW_LEN, "%lu", *ul);
  172. }