aboutsummaryrefslogtreecommitdiff
path: root/src/commands.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/commands.c346
1 files changed, 346 insertions, 0 deletions
diff --git a/src/commands.c b/src/commands.c
new file mode 100644
index 0000000..10e4eb8
--- /dev/null
+++ b/src/commands.c
@@ -0,0 +1,346 @@
1#include "commands.h"
2
3/* Arg parsing functions *****************************************************/
4
5CommandArgs * solve_parse_args(int c, char **v);
6CommandArgs * help_parse_args(int c, char **v);
7CommandArgs * print_parse_args(int c, char **v);
8CommandArgs * parse_no_arg(int c, char **v);
9
10/* Exec functions ************************************************************/
11
12static void solve_exec(CommandArgs *args);
13static void steps_exec(CommandArgs *args);
14static void commands_exec(CommandArgs *args);
15static void print_exec(CommandArgs *args);
16static void help_exec(CommandArgs *args);
17static void quit_exec(CommandArgs *args);
18static void version_exec(CommandArgs *args);
19
20/* Local functions ***********************************************************/
21
22static bool read_step(CommandArgs *args, char *str);
23static bool read_scramble(int c, char **v, CommandArgs *args);
24
25/* Commands ******************************************************************/
26
27Command
28solve_cmd = {
29 .name = "solve",
30 .usage = "solve STEP [OPTIONS] SCRAMBLE",
31 .description = "Solve a step",
32 .parse_args = solve_parse_args,
33 .exec = solve_exec
34};
35
36Command
37steps_cmd = {
38 .name = "steps",
39 .usage = "steps",
40 .description = "List available steps",
41 .parse_args = parse_no_arg,
42 .exec = steps_exec
43};
44
45Command
46commands_cmd = {
47 .name = "commands",
48 .usage = "commands",
49 .description = "List available commands",
50 .parse_args = parse_no_arg,
51 .exec = commands_exec
52};
53
54Command
55print_cmd = {
56 .name = "print",
57 .usage = "print SCRAMBLE",
58 .description = "Print written description of the cube",
59 .parse_args = print_parse_args,
60 .exec = print_exec,
61};
62
63Command
64help_cmd = {
65 .name = "help",
66 .usage = "help [COMMAND]",
67 .description = "Display nissy manual page or help on specific command",
68 .parse_args = help_parse_args,
69 .exec = help_exec,
70};
71
72Command
73quit_cmd = {
74 .name = "quit",
75 .usage = "quit",
76 .description = "Quit nissy",
77 .parse_args = parse_no_arg,
78 .exec = quit_exec,
79};
80
81Command
82version_cmd = {
83 .name = "version",
84 .usage = "version",
85 .description = "print nissy version",
86 .parse_args = parse_no_arg,
87 .exec = version_exec,
88};
89
90Command *commands[NCOMMANDS] = {
91 &commands_cmd,
92 &help_cmd,
93 &print_cmd,
94 &quit_cmd,
95 &solve_cmd,
96 &steps_cmd,
97 &version_cmd,
98};
99
100/* Arg parsing functions implementation **************************************/
101
102CommandArgs *
103solve_parse_args(int c, char **v)
104{
105 int i;
106 long val;
107
108 CommandArgs *a = malloc(sizeof(CommandArgs));
109
110 a->success = false;
111 a->opts = malloc(sizeof(SolveOptions));
112 a->step = steps[0];
113 a->command = NULL;
114 a->scramble = NULL;
115
116 a->opts->min_moves = 0;
117 a->opts->max_moves = 20;
118 a->opts->max_solutions = 1;
119 a->opts->optimal_only = false;
120 a->opts->can_niss = false;
121 a->opts->verbose = false;
122 a->opts->all = false;
123 a->opts->print_number = true;
124
125 for (i = 0; i < c; i++) {
126 if (!strcmp(v[i], "-m")) {
127 val = strtol(v[++i], NULL, 10);
128 if (val < 0 || val > 100) {
129 fprintf(stderr,
130 "Invalid min number of moves.\n");
131 return a;
132 }
133 a->opts->min_moves = val;
134 } else if (!strcmp(v[i], "-M")) {
135 val = strtol(v[++i], NULL, 10);
136 if (val < 0 || val > 100) {
137 fprintf(stderr,
138 "Invalid max number of moves.\n");
139 return a;
140 }
141 a->opts->max_moves = val;
142 } else if (!strcmp(v[i], "-s")) {
143 val = strtol(v[++i], NULL, 10);
144 if (val < 1 || val > 1000000) {
145 fprintf(stderr,
146 "Invalid number of solutions.\n");
147 return a;
148 }
149 a->opts->max_solutions = val;
150 } else if (!strcmp(v[i], "-o")) {
151 a->opts->optimal_only = true;
152 } else if (!strcmp(v[i], "-n")) {
153 a->opts->can_niss = true;
154 } else if (!strcmp(v[i], "-v")) {
155 a->opts->verbose = true;
156 } else if (!strcmp(v[i], "-a")) {
157 a->opts->all = true;
158 } else if (!strcmp(v[i], "-p")) {
159 a->opts->print_number = false;
160 } else if (!read_step(a, v[i])) {
161 break;
162 }
163 }
164
165 a->success = read_scramble(c-i, &v[i], a);
166 return a;
167}
168
169CommandArgs *
170help_parse_args(int c, char **v)
171{
172 int i;
173 CommandArgs *a = malloc(sizeof(CommandArgs));
174
175 a->scramble = NULL;
176 a->opts = NULL;
177 a->step = NULL;
178 a->command = NULL;
179
180 if (c == 1) {
181 for (i = 0; i < NCOMMANDS; i++)
182 if (commands[i] != NULL &&
183 !strcmp(v[0], commands[i]->name))
184 a->command = commands[i];
185 if (a->command == NULL)
186 fprintf(stderr, "%s: command not found\n", v[0]);
187 }
188
189 a->success = c == 0 || (c == 1 && a->command != NULL);
190 return a;
191}
192
193CommandArgs *
194parse_no_arg(int c, char **v)
195{
196 CommandArgs *a = malloc(sizeof(CommandArgs));
197
198 a->success = true;
199
200 return a;
201}
202
203CommandArgs *
204print_parse_args(int c, char **v)
205{
206 CommandArgs *a = malloc(sizeof(CommandArgs));
207
208 a->success = read_scramble(c, v, a);
209 return a;
210}
211
212/* Exec functions implementation *********************************************/
213
214static void
215solve_exec(CommandArgs *args)
216{
217 Cube c;
218 AlgList *sols;
219
220 init_symcoord();
221
222 c = apply_alg(args->scramble, (Cube){0});
223 sols = solve(c, args->step, args->opts);
224
225 print_alglist(sols, args->opts->print_number);
226 free_alglist(sols);
227}
228
229static void
230steps_exec(CommandArgs *args)
231{
232 int i;
233
234 for (i = 0; i < NSTEPS && steps[i] != NULL; i++)
235 printf("%-15s %s\n", steps[i]->shortname, steps[i]->name);
236}
237
238static void
239commands_exec(CommandArgs *args)
240{
241 int i;
242
243 for (i = 0; i < NCOMMANDS && commands[i] != NULL; i++)
244 printf("%s\n", commands[i]->usage);
245
246}
247
248static void
249print_exec(CommandArgs *args)
250{
251 init_moves();
252 print_cube(apply_alg(args->scramble, (Cube){0}));
253}
254
255static void
256help_exec(CommandArgs *args)
257{
258 /* TODO: print full nissy manpage */
259 if (args->command == NULL) {
260 printf("Type help COMMAND for information on a ");
261 printf("specific command.\n");
262 printf("A more complete manual page is work in progress.\n");
263 } else {
264 printf("Command %s: %s\nusage: %s\n", args->command->name,
265 args->command->description, args->command->usage);
266 }
267}
268
269static void
270quit_exec(CommandArgs *args)
271{
272 exit(0);
273}
274
275static void
276version_exec(CommandArgs *args)
277{
278 printf(VERSION"\n");
279}
280
281/* Local functions implementation ********************************************/
282
283static bool
284read_step(CommandArgs *args, char *str)
285{
286 int i;
287
288 for (i = 0; i < NSTEPS; i++) {
289 if (steps[i] != NULL && !strcmp(steps[i]->shortname, str)) {
290 args->step = steps[i];
291 return true;
292 }
293 }
294
295 return false;
296}
297
298static bool
299read_scramble(int c, char **v, CommandArgs *args)
300{
301 int i, k, n;
302 unsigned int j;
303 char *algstr;
304
305 if (new_alg(v[0])->len == 0) {
306 fprintf(stderr, "%s: moves or option unrecognized\n", v[0]);
307 return false;
308 }
309
310 n = 0;
311 for(i = 0; i < c; i++)
312 n += strlen(v[i]);
313
314 algstr = malloc((n + 1) * sizeof(char));
315 k = 0;
316 for (i = 0; i < c; i++)
317 for (j = 0; j < strlen(v[i]); j++)
318 algstr[k++] = v[i][j];
319 algstr[k] = 0;
320
321 args->scramble = new_alg(algstr);
322 free(algstr);
323
324 if (args->scramble->len == 0)
325 fprintf(stderr, "Error reading scramble\n");
326
327 return args->scramble->len > 0;
328}
329
330/* Public functions implementation *******************************************/
331
332void
333free_args(CommandArgs *args)
334{
335 if (args == NULL)
336 return;
337
338 if (args->scramble != NULL)
339 free_alg(args->scramble);
340 if (args->opts != NULL)
341 free(args->opts);
342
343 /* step and command must not be freed, they are static! */
344
345 free(args);
346}

Generated with cgit - Back to sebastiano.tronto.net