args.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #ifndef __ARGS_H__
  2. #define __ARGS_H__
  3. #include <stdlib.h>
  4. #include <argp.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include "io.h"
  8. const char *argp_program_version = "Dice 0.9";
  9. const char *argp_program_bug_address = "https://notabug.org/cryptarch/dice/issues";
  10. /*
  11. OPTIONS. Field 1 in ARGP.
  12. Order of fields: {NAME, KEY, ARG, FLAGS, DOC}.
  13. */
  14. static struct argp_option options[] = {
  15. {"prompt", 'p', "STRING", 0, "Set the dice interactive prompt to STRING.\n(Default: 'dice> ')"},
  16. {"seed", 's', "NUMBER", 0, "Set the seed to NUMBER. (Default is obtained from /dev/urandom.)"},
  17. {"help", 'h', NULL, 0, "Print this help message."},
  18. {"version", 'v', NULL, 0, "Print version information."},
  19. {0}
  20. };
  21. /*
  22. PARSER. Field 2 in ARGP.
  23. Order of parameters: KEY, ARG, STATE.
  24. */
  25. static error_t parse_opt (int key, char *arg, struct argp_state *state) {
  26. struct arguments *arguments = state->input;
  27. switch (key) {
  28. case 'p':
  29. {
  30. int prompt_length = strlen(arg);
  31. arguments->prompt = (char*)malloc(prompt_length*sizeof(char));
  32. memset(arguments->prompt, 0, prompt_length);
  33. strncpy(arguments->prompt, arg, prompt_length + 1);
  34. }
  35. break;
  36. case 'h':
  37. {
  38. argp_state_help(state, stdout, ARGP_HELP_USAGE | ARGP_HELP_LONG | ARGP_HELP_DOC);
  39. exit(EXIT_SUCCESS);
  40. }
  41. break;
  42. case 's':
  43. {
  44. char *arg_iter;
  45. for(arg_iter = arg; *arg_iter != '\0'; ++arg_iter) {
  46. if(!isdigit(*arg_iter)) {
  47. fprintf(stderr, "The random seed must be a number between 0 and %u.\n", UINT_MAX);
  48. exit(1);
  49. }
  50. }
  51. char *s_endptr;
  52. errno = 0;
  53. arguments->seed = strtol(arg, &s_endptr, 10);
  54. if((errno == ERANGE && (arguments->seed == LONG_MAX || arguments->seed == LONG_MIN))
  55. || (errno != 0 && arguments->seed == 0)) {
  56. fprintf(stderr, "Error %d (%s) setting seed to %s.\n", errno, strerror(errno), arg);
  57. arguments->seed_set = false;
  58. return 1;
  59. } else {
  60. arguments->seed_set = true;
  61. }
  62. }
  63. break;
  64. case 'v':
  65. {
  66. printf("%s\n", argp_program_version);
  67. exit(0);
  68. }
  69. break;
  70. case ARGP_KEY_ARG:
  71. {
  72. {
  73. arguments->mode = SCRIPTED;
  74. if(0 != strcmp(arg, "-")) {
  75. errno = 0;
  76. arguments->ist = fopen(arg, "r");
  77. if(arguments->ist == NULL) {
  78. fprintf(stderr, "Error %d (%s) opening file %s\n", errno, strerror(errno), arg);
  79. exit(1);
  80. }
  81. }
  82. }
  83. }
  84. break;
  85. default:
  86. return ARGP_ERR_UNKNOWN;
  87. }
  88. return 0;
  89. }
  90. /*
  91. ARGS_DOC. Field 3 in ARGP.
  92. A description of the non-option command-line arguments
  93. that we accept.
  94. */
  95. static char args_doc[] = "[file]";
  96. /*
  97. DOC. Field 4 in ARGP.
  98. Program documentation.
  99. */
  100. static char doc[] = "Dice -- An interpreter for standard dice notation (qv Wikipedia:Dice_notation)";
  101. /*
  102. The ARGP structure itself.
  103. */
  104. static struct argp argp = {options, parse_opt, args_doc, doc};
  105. #endif // __ARGS_H__