Human68k CUI emulator with sound.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmdline.c 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include "cmdline.h"
  5. void cmdline_print_help(char *argv0, struct cmdline_option *opts, char *args_text) {
  6. printf("Usage: %s [options] %s\n", argv0, args_text);
  7. for(struct cmdline_option *opt = opts; opt->option_type != TYPE_END; opt++) {
  8. printf("\t");
  9. int l = 0;
  10. if(opt->opt_char) {
  11. printf("-%c", opt->opt_char);
  12. l += 2;
  13. }
  14. if(opt->opt_char && opt->opt_long) {
  15. printf(", ");
  16. l += 2;
  17. }
  18. if(opt->opt_long) {
  19. printf("--%s", opt->opt_long);
  20. l += 2 + strlen(opt->opt_long);
  21. }
  22. if(opt->option_type == TYPE_REQUIRED) {
  23. char *arg_name = opt->arg_name ? opt->arg_name : "X";
  24. printf(" <%s>", arg_name);
  25. l += 3 + strlen(arg_name);
  26. }
  27. else if(opt->option_type == TYPE_OPTIONAL) {
  28. char *arg_name = opt->arg_name ? opt->arg_name : "X";
  29. printf(" [%s]", arg_name);
  30. l += 3 + strlen(arg_name);
  31. }
  32. #define ALIGN 20
  33. if(l < ALIGN)
  34. for(int i = ALIGN; i > l; i--)
  35. printf(" ");
  36. if(opt->opt_help) printf(" %s\n", opt->opt_help);
  37. }
  38. }
  39. static void cmdline_set_option_argument(struct cmdline_option *opt, char *str) {
  40. switch(opt->option_argument_type) {
  41. case TYPE_INT:
  42. if(opt->target)
  43. *((int *)opt->target) = strtol(str, 0, 0);
  44. break;
  45. case TYPE_FLOAT:
  46. if(opt->target)
  47. *((float *)opt->target) = strtof(str, 0);
  48. break;
  49. case TYPE_STRING:
  50. if(opt->target)
  51. *((char **)opt->target) = str;
  52. break;
  53. default:
  54. break;
  55. }
  56. }
  57. int cmdline_parse_args(int argc, char **argv, struct cmdline_option *opts, int num_required, int max_args, char *args_text) {
  58. struct cmdline_option *expecting_opt = 0;
  59. int first_nonopt = 1;
  60. int stop_parsing = 0;
  61. for(int i = 1; i < argc; i++) {
  62. if(argv[i][0] == '-' && argv[i][1] != 0 && !stop_parsing) {
  63. if(argv[i][1] == '-' && argv[i][2] == 0) {
  64. stop_parsing = 1;
  65. } else if((argv[i][1] == 'h' && argv[i][2] == 0) || !strcmp(argv[i], "--help")) {
  66. cmdline_print_help(argv[0], opts, args_text);
  67. return -1;
  68. } else {
  69. if(expecting_opt && expecting_opt->option_type == TYPE_REQUIRED)
  70. fprintf(stderr, "Required argument not found: %s\n", argv[first_nonopt-1]);
  71. expecting_opt = 0;
  72. int found = 0;
  73. for(struct cmdline_option *opt = opts; opt->option_type != TYPE_END; opt++) {
  74. if(opt->opt_char > 0 && argv[i][1] == opt->opt_char) {
  75. if(opt->option_type == TYPE_SWITCH) {
  76. if(opt->target) *((int *)opt->target) = 1;
  77. } else if(argv[i][2] != 0) {
  78. cmdline_set_option_argument(opt, &argv[i][2]);
  79. } else {
  80. expecting_opt = opt;
  81. }
  82. found = 1;
  83. } else if(opt->opt_long && argv[i][1] == '-' && !strcmp(&argv[i][2], opt->opt_long)) {
  84. if(opt->option_type == TYPE_SWITCH) {
  85. if(opt->target) *((int *)opt->target) = 1;
  86. } else {
  87. expecting_opt = opt;
  88. }
  89. found = 1;
  90. }
  91. }
  92. if(!found) {
  93. fprintf(stderr, "Unknown option: %s\n", argv[i]);
  94. }
  95. }
  96. } else if(expecting_opt) {
  97. cmdline_set_option_argument(expecting_opt, argv[i]);
  98. expecting_opt = 0;
  99. } else continue; // non-opt opt, just skip over it and don't execute code below
  100. char *curarg = argv[i];
  101. for(int j = i-1; j >= first_nonopt; j--) {
  102. argv[j+1] = argv[j];
  103. }
  104. argv[first_nonopt] = curarg;
  105. first_nonopt++;
  106. }
  107. if(argc - first_nonopt < num_required) {
  108. cmdline_print_help(argv[0], opts, args_text);
  109. return -1;
  110. }
  111. return first_nonopt;
  112. }