diff options
Diffstat (limited to '')
| -rw-r--r-- | shell.c | 212 |
1 files changed, 177 insertions, 35 deletions
| @@ -13,10 +13,36 @@ | |||
| 13 | #define SOLUTIONS_BUFFER_SIZE 500000 /* Should be enough */ | 13 | #define SOLUTIONS_BUFFER_SIZE 500000 /* Should be enough */ |
| 14 | #define MAX_PATH_LENGTH 10000 /* Should be enough */ | 14 | #define MAX_PATH_LENGTH 10000 /* Should be enough */ |
| 15 | 15 | ||
| 16 | #define _flag_cube "-cube" | ||
| 17 | #define _flag_perm "-perm" | ||
| 18 | #define _flag_command "-command" | ||
| 19 | #define _flag_str_cube "-cubestr" | ||
| 20 | #define _flag_format "-format" | ||
| 21 | #define _flag_format_in "-fin" | ||
| 22 | #define _flag_format_out "-fout" | ||
| 23 | #define _flag_moves "-moves" | ||
| 24 | #define _flag_trans "-trans" | ||
| 25 | #define _flag_solver "-solver" | ||
| 26 | #define _flag_options "-options" | ||
| 27 | #define _flag_nisstype "-nisstype" | ||
| 28 | #define _flag_minmoves "-m" | ||
| 29 | #define _flag_maxmoves "-M" | ||
| 30 | #define _flag_optimal "-O" | ||
| 31 | #define _flag_maxsolutions "-n" | ||
| 32 | |||
| 33 | #define _info_cubeformat(cube) cube " must be given in B32 format." | ||
| 34 | #define _info_movesformat "The accepted moves are U, D, R, L, F and B, " \ | ||
| 35 | "optionally followed by a 2, a ' or a 3." | ||
| 36 | #define _info_transformat "The transformation must be given in the format " \ | ||
| 37 | "(rotation|mirrored) (2 letters), for exmple " \ | ||
| 38 | "'rotation UF' or 'mirrored BL'." | ||
| 39 | #define _info_formats "The available formats are H48, B32 and SRC." | ||
| 40 | |||
| 16 | typedef struct { | 41 | typedef struct { |
| 17 | int command_index; | 42 | int command_index; |
| 18 | char cube[22]; | 43 | char cube[22]; |
| 19 | char cube_perm[22]; | 44 | char cube_perm[22]; |
| 45 | char *str_command; | ||
| 20 | char *str_cube; | 46 | char *str_cube; |
| 21 | char *str_format; | 47 | char *str_format; |
| 22 | char *str_format_in; | 48 | char *str_format_in; |
| @@ -45,6 +71,7 @@ static int64_t randomcube_exec(args_t *); | |||
| 45 | static int64_t datasize_exec(args_t *); | 71 | static int64_t datasize_exec(args_t *); |
| 46 | static int64_t gendata_exec(args_t *); | 72 | static int64_t gendata_exec(args_t *); |
| 47 | static int64_t solve_exec(args_t *); | 73 | static int64_t solve_exec(args_t *); |
| 74 | static int64_t help_exec(args_t *); | ||
| 48 | 75 | ||
| 49 | static int parse_args(int, char **, args_t *); | 76 | static int parse_args(int, char **, args_t *); |
| 50 | static bool parse_int8(char *, int8_t *); | 77 | static bool parse_int8(char *, int8_t *); |
| @@ -52,6 +79,7 @@ static bool parse_int64(char *, int64_t *); | |||
| 52 | 79 | ||
| 53 | static bool set_cube(int, char **, args_t *); | 80 | static bool set_cube(int, char **, args_t *); |
| 54 | static bool set_cube_perm(int, char **, args_t *); | 81 | static bool set_cube_perm(int, char **, args_t *); |
| 82 | static bool set_str_command(int, char **, args_t *); | ||
| 55 | static bool set_str_cube(int, char **, args_t *); | 83 | static bool set_str_cube(int, char **, args_t *); |
| 56 | static bool set_str_format(int, char **, args_t *); | 84 | static bool set_str_format(int, char **, args_t *); |
| 57 | static bool set_str_format_in(int, char **, args_t *); | 85 | static bool set_str_format_in(int, char **, args_t *); |
| @@ -68,24 +96,6 @@ static bool set_maxsolutions(int, char **, args_t *); | |||
| 68 | static bool set_id(int, char **, args_t *); | 96 | static bool set_id(int, char **, args_t *); |
| 69 | 97 | ||
| 70 | static uint64_t rand64(void); | 98 | static uint64_t rand64(void); |
| 71 | |||
| 72 | #define COMMAND(N, E) { .name = N, .exec = E } | ||
| 73 | struct { | ||
| 74 | char *name; | ||
| 75 | int64_t (*exec)(args_t *); | ||
| 76 | } commands[] = { | ||
| 77 | COMMAND("compose", compose_exec), | ||
| 78 | COMMAND("inverse", inverse_exec), | ||
| 79 | COMMAND("applymoves", applymoves_exec), | ||
| 80 | COMMAND("applytrans", applytrans_exec), | ||
| 81 | COMMAND("frommoves", frommoves_exec), | ||
| 82 | COMMAND("convert", convert_exec), | ||
| 83 | COMMAND("randomcube", randomcube_exec), | ||
| 84 | COMMAND("datasize", datasize_exec), | ||
| 85 | COMMAND("gendata", gendata_exec), | ||
| 86 | COMMAND("solve", solve_exec), | ||
| 87 | COMMAND(NULL, NULL) | ||
| 88 | }; | ||
| 89 | 99 | ||
| 90 | #define OPTION(N, A, S) { .name = N, .nargs = A, .set = S } | 100 | #define OPTION(N, A, S) { .name = N, .nargs = A, .set = S } |
| 91 | struct { | 101 | struct { |
| @@ -93,23 +103,118 @@ struct { | |||
| 93 | int nargs; | 103 | int nargs; |
| 94 | bool (*set)(int, char **, args_t *); | 104 | bool (*set)(int, char **, args_t *); |
| 95 | } options[] = { | 105 | } options[] = { |
| 96 | OPTION("-cube", 1, set_cube), | 106 | OPTION(_flag_cube, 1, set_cube), |
| 97 | OPTION("-perm", 1, set_cube_perm), | 107 | OPTION(_flag_perm, 1, set_cube_perm), |
| 98 | OPTION("-cubestr", 1, set_str_cube), | 108 | OPTION(_flag_command, 1, set_str_command), |
| 99 | OPTION("-format", 1, set_str_format), | 109 | OPTION(_flag_str_cube, 1, set_str_cube), |
| 100 | OPTION("-fin", 1, set_str_format_in), | 110 | OPTION(_flag_format, 1, set_str_format), |
| 101 | OPTION("-fout", 1, set_str_format_out), | 111 | OPTION(_flag_format_in, 1, set_str_format_in), |
| 102 | OPTION("-moves", 1, set_str_moves), | 112 | OPTION(_flag_format_out, 1, set_str_format_out), |
| 103 | OPTION("-trans", 1, set_str_trans), | 113 | OPTION(_flag_moves, 1, set_str_moves), |
| 104 | OPTION("-solver", 1, set_str_solver), | 114 | OPTION(_flag_trans, 1, set_str_trans), |
| 105 | OPTION("-options", 1, set_str_options), /* TODO: remove, use only solver */ | 115 | OPTION(_flag_solver, 1, set_str_solver), |
| 106 | OPTION("-nisstype", 1, set_str_nisstype), /* TODO: remove, use flags */ | 116 | OPTION(_flag_options, 1, set_str_options), /* TODO: remove, use only solver */ |
| 107 | OPTION("-m", 1, set_minmoves), | 117 | OPTION(_flag_nisstype, 1, set_str_nisstype), /* TODO: remove, use flags */ |
| 108 | OPTION("-M", 1, set_maxmoves), | 118 | OPTION(_flag_minmoves, 1, set_minmoves), |
| 109 | OPTION("-O", 1, set_optimal), | 119 | OPTION(_flag_maxmoves, 1, set_maxmoves), |
| 110 | OPTION("-n", 1, set_maxsolutions), | 120 | OPTION(_flag_optimal, 1, set_optimal), |
| 121 | OPTION(_flag_maxsolutions, 1, set_maxsolutions), | ||
| 111 | OPTION(NULL, 0, NULL) | 122 | OPTION(NULL, 0, NULL) |
| 112 | }; | 123 | }; |
| 124 | |||
| 125 | #define COMMAND(N, S, D, E) { .name = N, .syn = S, .desc = D, .exec = E } | ||
| 126 | struct { | ||
| 127 | char *name; | ||
| 128 | char *syn; | ||
| 129 | char *desc; | ||
| 130 | int64_t (*exec)(args_t *); | ||
| 131 | } commands[] = { | ||
| 132 | /* TODO: add synopsis and description here */ | ||
| 133 | COMMAND( | ||
| 134 | "compose", | ||
| 135 | "compose " _flag_cube " CUBE " _flag_perm " PERM", | ||
| 136 | "Apply on CUBE the permutation defined by PERM. " | ||
| 137 | _info_cubeformat("CUBE and PERM"), | ||
| 138 | compose_exec | ||
| 139 | ), | ||
| 140 | COMMAND( | ||
| 141 | "inverse", | ||
| 142 | "inverse " _flag_cube " CUBE ", | ||
| 143 | "Compute the inverse of the given CUBE. " | ||
| 144 | _info_cubeformat("CUBE"), | ||
| 145 | inverse_exec | ||
| 146 | ), | ||
| 147 | COMMAND( | ||
| 148 | "applymoves", | ||
| 149 | "applymoves " _flag_cube " CUBE " _flag_moves " MOVES", | ||
| 150 | "Apply the given MOVES to the given CUBE. " | ||
| 151 | _info_cubeformat("CUBE") " " _info_movesformat, | ||
| 152 | applymoves_exec | ||
| 153 | ), | ||
| 154 | COMMAND( | ||
| 155 | "applytrans", | ||
| 156 | "applytrans " _flag_cube " CUBE " _flag_trans " TRANS", | ||
| 157 | "Apply the single transformation TRANS to the given CUBE. " | ||
| 158 | _info_cubeformat("CUBE") " " _info_transformat, | ||
| 159 | applytrans_exec | ||
| 160 | ), | ||
| 161 | COMMAND( | ||
| 162 | "frommoves", | ||
| 163 | "frommoves " _flag_moves " MOVES", | ||
| 164 | "Return the cube obtained by applying the given MOVES " | ||
| 165 | "to a solved cube. " _info_movesformat, | ||
| 166 | frommoves_exec | ||
| 167 | ), | ||
| 168 | COMMAND( | ||
| 169 | "convert", | ||
| 170 | "convert " _flag_str_cube " CUBESTR " | ||
| 171 | _flag_format_in " FORMAT_IN " _flag_format_out " FORMAT_OUT", | ||
| 172 | "Convert the cube described by CUBESTR from FORMAT_IN to " | ||
| 173 | "FORMAT_OUT." | ||
| 174 | _info_formats " " | ||
| 175 | "CUBESTR must be a valid cube in the FORMAT_IN format.", | ||
| 176 | convert_exec | ||
| 177 | ), | ||
| 178 | COMMAND( | ||
| 179 | "randomcube", | ||
| 180 | "randomcube", | ||
| 181 | "Returns a random cube in B32 format.", | ||
| 182 | randomcube_exec | ||
| 183 | ), | ||
| 184 | COMMAND( | ||
| 185 | "datasize", | ||
| 186 | "datasize" _flag_solver " SOLVER " _flag_options " OPTIONS", | ||
| 187 | "Return the size in bytes of the data table used by " | ||
| 188 | "SOLVER when called with the given OPTIONS.", | ||
| 189 | datasize_exec | ||
| 190 | ), | ||
| 191 | COMMAND( | ||
| 192 | "gendata", | ||
| 193 | "gendata" _flag_solver " SOLVER " _flag_options " OPTIONS", | ||
| 194 | "Generate the data table used by " | ||
| 195 | "SOLVER when called with the given OPTIONS.", | ||
| 196 | gendata_exec | ||
| 197 | ), | ||
| 198 | COMMAND( | ||
| 199 | "solve", | ||
| 200 | "solve" _flag_solver " SOLVER " _flag_options " OPTIONS " | ||
| 201 | "[" _flag_minmoves " n] [" _flag_maxmoves " N] " | ||
| 202 | _flag_cube " CUBE", | ||
| 203 | "Solve the given CUBE using SOLVER with the given OPTIONS, " | ||
| 204 | "using at least n and at most N moves. " | ||
| 205 | _info_cubeformat("CUBE"), | ||
| 206 | solve_exec | ||
| 207 | ), | ||
| 208 | COMMAND( | ||
| 209 | "help", | ||
| 210 | "help [" _flag_command " COMMAND]", | ||
| 211 | "If no COMMAND is specified, prints some generic information " | ||
| 212 | "and the list of commands. Otherwise it prints detailed " | ||
| 213 | "information about the specified COMMAND.", | ||
| 214 | help_exec | ||
| 215 | ), | ||
| 216 | COMMAND(NULL, NULL, NULL, NULL) | ||
| 217 | }; | ||
| 113 | 218 | ||
| 114 | char *tablepaths[] = { | 219 | char *tablepaths[] = { |
| 115 | "tables/", | 220 | "tables/", |
| @@ -397,6 +502,33 @@ solve_exec(args_t *args) | |||
| 397 | return 0; | 502 | return 0; |
| 398 | } | 503 | } |
| 399 | 504 | ||
| 505 | static int64_t | ||
| 506 | help_exec(args_t *args) | ||
| 507 | { | ||
| 508 | int i; | ||
| 509 | |||
| 510 | if (args->str_command == NULL || args->str_command[0] == '\0') { | ||
| 511 | printf("This is a rudimentary shell for the H48 library.\n"); | ||
| 512 | printf("Available commands and usage:\n\n"); | ||
| 513 | for (i = 0; commands[i].name != NULL; i++) | ||
| 514 | printf("%-15s%s\n", commands[i].name, commands[i].syn); | ||
| 515 | printf("\nUse 'help COMMAND' for more information.\n"); | ||
| 516 | } else { | ||
| 517 | for (i = 0; commands[i].name != NULL; i++) | ||
| 518 | if (!strcmp(args->str_command, commands[i].name)) | ||
| 519 | break; | ||
| 520 | if (commands[i].name == NULL) { | ||
| 521 | printf("Unknown command %s\n", args->str_command); | ||
| 522 | return 1; | ||
| 523 | } | ||
| 524 | printf("Command %s\n\n", commands[i].name); | ||
| 525 | printf("Synopsis: %s\n\n", commands[i].syn); | ||
| 526 | printf("Description: %s\n", commands[i].desc); | ||
| 527 | } | ||
| 528 | |||
| 529 | return 0; | ||
| 530 | } | ||
| 531 | |||
| 400 | static int | 532 | static int |
| 401 | parse_args(int argc, char **argv, args_t *args) | 533 | parse_args(int argc, char **argv, args_t *args) |
| 402 | { | 534 | { |
| @@ -507,6 +639,14 @@ set_cube_perm(int argc, char **argv, args_t *args) | |||
| 507 | } | 639 | } |
| 508 | 640 | ||
| 509 | static bool | 641 | static bool |
| 642 | set_str_command(int argc, char **argv, args_t *args) | ||
| 643 | { | ||
| 644 | args->str_command = argv[0]; | ||
| 645 | |||
| 646 | return true; | ||
| 647 | } | ||
| 648 | |||
| 649 | static bool | ||
| 510 | set_str_cube(int argc, char **argv, args_t *args) | 650 | set_str_cube(int argc, char **argv, args_t *args) |
| 511 | { | 651 | { |
| 512 | args->str_cube = argv[0]; | 652 | args->str_cube = argv[0]; |
| @@ -602,7 +742,8 @@ set_maxsolutions(int argc, char **argv, args_t *args) | |||
| 602 | return parse_int64(argv[0], &args->maxsolutions); | 742 | return parse_int64(argv[0], &args->maxsolutions); |
| 603 | } | 743 | } |
| 604 | 744 | ||
| 605 | void log_stderr(const char *str, ...) | 745 | void |
| 746 | log_stderr(const char *str, ...) | ||
| 606 | { | 747 | { |
| 607 | va_list args; | 748 | va_list args; |
| 608 | 749 | ||
| @@ -611,7 +752,8 @@ void log_stderr(const char *str, ...) | |||
| 611 | va_end(args); | 752 | va_end(args); |
| 612 | } | 753 | } |
| 613 | 754 | ||
| 614 | int main(int argc, char **argv) | 755 | int |
| 756 | main(int argc, char **argv) | ||
| 615 | { | 757 | { |
| 616 | int parse_error; | 758 | int parse_error; |
| 617 | args_t args; | 759 | args_t args; |
