getlopt.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. getlopt: command line option/parameter parsing
  3. copyright ?-2008 by the mpg123 project - free software under the terms of the LGPL 2.1
  4. see COPYING and AUTHORS files in distribution or http://mpg123.org
  5. initially written Oliver Fromme
  6. old timestamp: Tue Apr 8 07:15:13 MET DST 1997
  7. */
  8. #include "config.h"
  9. #include "compat.h"
  10. #include "getlopt.h"
  11. #include "debug.h"
  12. int loptind = 1; /* index in argv[] */
  13. int loptchr = 0; /* index in argv[loptind] */
  14. char *loptarg; /* points to argument if present, else to option */
  15. topt *findopt (int islong, char *opt, topt *opts)
  16. {
  17. if (!opts)
  18. return (0);
  19. while (opts->lname) {
  20. if (islong) {
  21. if (!strcmp(opts->lname, opt))
  22. return (opts);
  23. }
  24. else
  25. if (opts->sname == *opt)
  26. return (opts);
  27. opts++;
  28. }
  29. return (0);
  30. }
  31. static int performoption (int argc, char *argv[], topt *opt)
  32. {
  33. int result = GLO_CONTINUE;
  34. /* this really is not supposed to happen, so the exit may be justified to create asap ficing pressure */
  35. #define prog_error() \
  36. { \
  37. fprintf(stderr, __FILE__ ":%i Option without type flag! This is a programming error! Developer: fix this ASAP to regain your honor.\n", __LINE__); \
  38. exit(1); \
  39. }
  40. debug2("performoption on %c / %s"
  41. , opt->sname ? opt->sname : '_', opt->lname ? opt->lname : "");
  42. if (!(opt->flags & GLO_ARG)) { /* doesn't take argument */
  43. if (opt->var) {
  44. if (opt->flags & GLO_CHAR) /* var is *char */
  45. {
  46. debug1("char at %p", opt->var);
  47. *((char *) opt->var) = (char) opt->value;\
  48. }
  49. else if(opt->flags & GLO_LONG)
  50. {
  51. debug1("long at %p", opt->var);
  52. *( (long *) opt->var ) = opt->value;
  53. }
  54. else if(opt->flags & GLO_INT)
  55. {
  56. debug1("int at %p", opt->var);
  57. *( (int *) opt->var ) = (int) opt->value;
  58. }
  59. /* GLO_DOUBLE is not supported here */
  60. else prog_error();
  61. debug("casting assignment done");
  62. }
  63. #if 0 /* Oliver: What was this for?! --ThOr */
  64. else
  65. result = opt->value ? opt->value : opt->sname;
  66. #endif
  67. }
  68. else { /* requires argument */
  69. debug("argument required");
  70. if (loptind >= argc)
  71. return (GLO_NOARG);
  72. loptarg = argv[loptind++]+loptchr;
  73. loptchr = 0;
  74. if (opt->var) {
  75. if (opt->flags & GLO_CHAR) /* var is *char */
  76. *((char **) opt->var) = compat_strdup(loptarg); /* valgrind claims lost memory here */
  77. else if(opt->flags & GLO_LONG)
  78. *((long *) opt->var) = atol(loptarg);
  79. else if(opt->flags & GLO_INT)
  80. *((int *) opt->var) = atoi(loptarg);
  81. else if(opt->flags & GLO_DOUBLE)
  82. *((double *) opt->var) = atof(loptarg);
  83. else prog_error();
  84. }
  85. #if 0 /* Oliver: What was this for?! --ThOr */
  86. else
  87. result = opt->value ? opt->value : opt->sname;
  88. #endif
  89. }
  90. if (opt->func)
  91. opt->func(loptarg);
  92. debug4("result: %i (%p, %li, %i)", result, opt->var, opt->value, opt->sname);
  93. return (result);
  94. }
  95. int getsingleopt (int argc, char *argv[], topt *opts)
  96. {
  97. char *thisopt;
  98. topt *opt;
  99. static char shortopt[2] = {0, 0};
  100. if (loptind >= argc)
  101. return (GLO_END);
  102. thisopt = argv[loptind];
  103. debug1("getsingleopt: %s", thisopt);
  104. if (!loptchr) { /* start new option string */
  105. if (thisopt[0] != '-' || !thisopt[1]) /* no more options */
  106. return (GLO_END);
  107. if (thisopt[1] == '-') { /* "--" */
  108. if (thisopt[2]) { /* long option */
  109. loptarg = thisopt+2;
  110. loptind++;
  111. if (!(opt = findopt(1, thisopt+2, opts)))
  112. return (GLO_UNKNOWN);
  113. else
  114. return (performoption(argc, argv, opt));
  115. }
  116. else { /* "--" == end of options */
  117. loptind++;
  118. return (GLO_END);
  119. }
  120. }
  121. else /* start short option(s) */
  122. loptchr = 1;
  123. }
  124. shortopt[0] = thisopt[loptchr];
  125. loptarg = shortopt;
  126. opt = findopt(0, thisopt+(loptchr++), opts);
  127. if (!thisopt[loptchr]) {
  128. loptind++;
  129. loptchr = 0;
  130. }
  131. if (!opt)
  132. return (GLO_UNKNOWN);
  133. else
  134. return (performoption(argc, argv, opt));
  135. }
  136. int getlopt (int argc, char *argv[], topt *opts)
  137. {
  138. int result;
  139. while ((result = getsingleopt(argc, argv, opts)) == GLO_CONTINUE);
  140. return (result);
  141. }
  142. /* EOF */