argument.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include "argument.h"
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdbool.h>
  5. int opt_i = 0;
  6. int opt_flat = 0;
  7. char *opt_val = NULL;
  8. int argc_ = 0;
  9. char **argv_ = NULL;
  10. struct arg_define *arg_;
  11. enum {
  12. normal = 0,
  13. at_end,
  14. continue_flat, // 如处理-abc这样连续的短选项
  15. } status;
  16. int continue_index = 0;
  17. bool exchange_one = false; // 只发生了一次exchange, 意味着新arg的下一个arg与该arg并非连接的关系
  18. // 如: zz -s -y -> -s zz -y,显然-s与zz并非连接关系
  19. bool initOpt(bool base, int argc, char **argv, struct arg_define *arg) {
  20. if (base)
  21. opt_i = 1;
  22. else
  23. opt_i = 0;
  24. argc_ = argc;
  25. argv_ = argv;
  26. arg_ = arg;
  27. opt_flat = 0;
  28. opt_val = NULL;
  29. status = normal;
  30. return argc_ != 0 && arg != NULL;
  31. }
  32. static int getReturn(struct arg_define *arg) {
  33. switch (arg->argument) {
  34. case no_argument:
  35. return arg->flat;
  36. case can_argument:
  37. if (!exchange_one && (status != continue_flat || argv_[opt_i][continue_index + 1] == '\0') && opt_i + 1 < argc_ && argv_[opt_i + 1][0] != '-') {
  38. opt_val = argv_[opt_i + 1];
  39. } else
  40. opt_val = NULL;
  41. return arg->flat;
  42. case must_argument:
  43. if (!exchange_one && (status != continue_flat && argv_[opt_i][continue_index + 1] == '\0') || opt_i + 1 >= argc_ && argv_[opt_i + 1][0] != '-') {
  44. fprintf(stderr, "-%c --%s : Lack of argument.\n", arg->ch, arg->name);
  45. return '?';
  46. }
  47. opt_val = argv_[opt_i + 1];
  48. return arg->flat;
  49. }
  50. fprintf(stderr, "%s : Error argument.\n", argv_[opt_i]);
  51. return '?';
  52. }
  53. static int getShort(char ch) {
  54. struct arg_define *arg = arg_;
  55. while (arg->ch != 0) {
  56. if (arg->ch != '?' && arg->ch == ch)
  57. return getReturn(arg);
  58. arg++;
  59. }
  60. fprintf(stderr, "-%c : Don't support argument.\n", ch);
  61. return '?';
  62. }
  63. static int getLong(char *name) {
  64. struct arg_define *arg = arg_;
  65. while (arg->ch != 0) {
  66. if (arg->name != NULL && !strcmp(arg->name, name))
  67. return getReturn(arg);
  68. arg++;
  69. }
  70. fprintf(stderr, "--%s : Don't support argument.\n", name);
  71. return '?';
  72. }
  73. static int getOpt_(void) {
  74. if (status == at_end)
  75. return 0;
  76. if (status == continue_flat) {
  77. if (argv_[opt_i][continue_index] == '\0') {
  78. opt_i ++;
  79. status = normal;
  80. continue_index = 0;
  81. } else {
  82. int re = getShort(argv_[opt_i][continue_index]);
  83. if (opt_val != NULL) {
  84. opt_i += 2;
  85. status = normal;
  86. continue_index = 0;
  87. } else
  88. continue_index++;
  89. return re;
  90. }
  91. }
  92. if (opt_i >= argc_) {
  93. status = at_end;
  94. return 0;
  95. }
  96. if (!strcmp(argv_[opt_i], "--")) { // 后面的参数全部当作非选项处理
  97. opt_i++;
  98. status = at_end;
  99. return 0;
  100. }
  101. if (strlen(argv_[opt_i]) < 2 || argv_[opt_i][0] != '-') { // 如果是短选型起码是-a两个字符,如果是长选项必然--开头也大于两个字符
  102. for (int i = opt_i + 1; i < argc_; i++) {
  103. if (!strcmp(argv_[i], "--"))
  104. break;
  105. if (argv_[i][0] == '-') { // 交换
  106. if (i + 1 < argc_ && argv_[i + 1][0] != '-') { // argv_[i + 1]可能是参数, 若不是参数移动他也没有关系
  107. char *tmp1 = argv_[i];
  108. char *tmp2 = argv_[i + 1];
  109. memmove(argv_ + opt_i + 2, argv_ + opt_i, (i - opt_i) * sizeof(char *));
  110. argv_[opt_i] = tmp1;
  111. argv_[opt_i + 1] = tmp2;
  112. } else {
  113. char *tmp = argv_[i];
  114. memmove(argv_ + opt_i + 1, argv_ + opt_i, (i - opt_i) * sizeof(char *));
  115. argv_[opt_i] = tmp;
  116. exchange_one = true;
  117. }
  118. goto continue_;
  119. }
  120. }
  121. // 寻找无果
  122. // opt_i不用增加1, 当前和后面的参数全部当作非选项处理
  123. status = at_end;
  124. return 0;
  125. }
  126. continue_:
  127. if (argv_[opt_i][0] == '-' && argv_[opt_i][1] != '-') {
  128. status = continue_flat;
  129. continue_index = 1;
  130. int re = getShort(argv_[opt_i][1]);
  131. if (opt_val != NULL) {
  132. opt_i += 2;
  133. status = normal;
  134. } else
  135. continue_index = 2;
  136. return re;
  137. }
  138. if (argv_[opt_i][0] == '-' && argv_[opt_i][1] == '-') {
  139. int re = getLong(argv_[opt_i] + 2);
  140. if (opt_val != NULL)
  141. opt_i += 2;
  142. else
  143. opt_i++;
  144. return re;
  145. }
  146. fprintf(stderr, "%s : Not support argument.\n", argv_[opt_i]);
  147. opt_i++;
  148. return '?'; // 理论上不应该会运算到这里
  149. }
  150. int getOpt(void) {
  151. exchange_one = false;
  152. opt_val = NULL;
  153. opt_flat = getOpt_();
  154. return opt_flat;
  155. }