typie | Minimal typing practice tool |
| download: https://git.y1.nz/archives/typie.tar.gz | |
| README | Files | Log | Refs | LICENSE |
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
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.