opt.c
1 2 #include <stdlib.h> 3 #include <stdio.h> 4 #include <limits.h> 5 6 #include "opt.h" 7 #include "typer.h" 8 9 #define ERROR(message) fprintf(stderr, COLOR_RED message COLOR_RESET); 10 #define ERRORARG(message, arg)\ 11 fprintf(stderr, COLOR_RED message COLOR_RESET, arg); 12 13 #define PROCESS_GROUP_SUCCESS 0 14 #define PROCESS_GROUP_FAILURE 1 15 #define PROCESS_GROUP_SKIP 2 16 #define PARSE_INT_FAILURE -1 17 18 int 19 parse_int(const char * arg) 20 { 21 char * endptr; 22 int ret; 23 ret = strtol(arg, &endptr, 10); 24 if (* endptr != '\0' || ret > INT_MAX || ret < INT_MIN) 25 return PARSE_INT_FAILURE; 26 return ret; 27 } 28 29 int 30 get_flag(char c) 31 { 32 switch (c) { 33 case 'l': return FLAG_LEARN_MODE; 34 case 'o': return FLAG_FILE; 35 case 't': return FLAG_TIME; 36 } 37 38 return 0; 39 } 40 41 int 42 process_flag_group(State * state, const char * group, const char * next) 43 { 44 int index; 45 char c; 46 int flag; 47 48 if (group[0] != '-') { 49 ERROR("Invalid flag format." "\n\n"); 50 return 1; 51 } 52 53 index = 1; 54 for (;;) { 55 c = group[index]; 56 57 if (c == '\0') 58 break; 59 60 flag = get_flag(c); 61 62 if (flag == 0) { 63 ERRORARG("Unrecognized flag: -%c." "\n\n", c); 64 return PROCESS_GROUP_FAILURE; 65 } 66 67 if ((state->flags & flag) != 0) { 68 ERRORARG("Repeated flag: -%c." "\n\n", c); 69 return PROCESS_GROUP_FAILURE; 70 } 71 72 state->flags |= flag; 73 74 if (flag == FLAG_FILE) { 75 if (next == NULL || group[index+1] != '\0') { 76 ERROR("Filename must follow -f." "\n\n"); 77 return PROCESS_GROUP_FAILURE; 78 } 79 80 state->outfile = next; 81 82 return PROCESS_GROUP_SKIP; 83 } 84 85 if (flag == FLAG_TIME) { 86 long int duration_seconds; 87 if (next == NULL || group[index+1] != '\0') { 88 ERROR("Integer must follow -t." "\n\n"); 89 return PROCESS_GROUP_FAILURE; 90 } 91 92 duration_seconds = parse_int(next); 93 if (duration_seconds == PARSE_INT_FAILURE) { 94 ERROR("Integer must follow -t." "\n\n"); 95 return PROCESS_GROUP_FAILURE; 96 } 97 state->duration_millis = duration_seconds * 1000; 98 99 return PROCESS_GROUP_SKIP; 100 } 101 102 index++; 103 } 104 105 return 0; 106 } 107 108 int 109 set_flags(State * state, int argc, const char * argv[]) 110 { 111 int index = 1; 112 const char * group; 113 const char * next; 114 int result; 115 116 if (argc == 2) 117 return 0; 118 119 if (argc == 1) { 120 ERROR("Not enough arguments." "\n\n"); 121 return 1; 122 } 123 124 for (;;) { 125 group = argv[index]; 126 next = (index+1 < argc-1) ? argv[index+1] : NULL; 127 128 result = process_flag_group(state, group, next); 129 if (result == PROCESS_GROUP_SKIP) 130 index++; 131 if (result == PROCESS_GROUP_FAILURE) 132 return 1; 133 134 index++; 135 if(index >= argc-1) /* last arg is PROMPT */ 136 break; 137 } 138 139 return 0; 140 } 141