diff --git a/src/utictactoe.c b/src/utictactoe.c index aa03731..5bf1c3b 100644 --- a/src/utictactoe.c +++ b/src/utictactoe.c @@ -6,6 +6,11 @@ #include #include "utictactoe.h" +#define OPTIONAL_ARGUMENT_IS_PRESENT \ + ((optarg == NULL && optind < argc && argv[optind][0] != '-') \ + ? (bool) (optarg = argv[optind++]) \ + : (optarg != NULL)) + void help(){ printf("usage: utictactoe ([-i LEVEL|-x N|-o N|-v|-V|-h] | -c FILE)\n"); printf("Play a utictactoe game with human or program players.\n"); @@ -18,45 +23,82 @@ void help(){ printf("-h, --help display this help and exit\n"); printf("Tactics list: random (0), clever (1)\n"); } + +int check_int_value ( char *value, int min, int max){ + char * end_ptr; + int result; + result = strtol(optarg, &end_ptr, 10); + if ( strcmp(end_ptr, "\0") != 0 ) { + return -1; + } + if ( result < min || result > max) { + return -1; + } + return result; +} + int main(int argc, char* argv[]) { int optc; + int cross_ai, round_ai = 0; int inception_level = 0; - bool contest, round_ai, cross_ai = false; + bool contest = false; - char * end_ptr; static struct option long_opts[] = { {"inception-level", optional_argument, 0, 'i'}, - {"cross-ai", no_argument, 0, 'x'}, - {"round-ai", no_argument, 0, 'o'}, + {"cross-ai", required_argument, 0, 'x'}, + {"round-ai", required_argument, 0, 'o'}, {"contest", no_argument, 0, 'c'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; - while ((optc = getopt_long (argc, argv, "i:xocvVh", long_opts, NULL)) != -1){ + + while ((optc = getopt_long (argc, argv, "i::x:o:cvVh", long_opts, NULL)) != -1){ switch (optc) { case 'i': /* 'a' option */ - printf ("Inception activated\n"); - if ( optarg ) { - inception_level = strtol(optarg, &end_ptr, 10); - assert ( strcmp(end_ptr,"\0") == 0); - assert ( inception_level >= 1 ); - assert ( inception_level <= 3 ); + if ( OPTIONAL_ARGUMENT_IS_PRESENT ) { + inception_level = check_int_value( optarg, 1, 3); + if ( inception_level == -1 ) { + fprintf(stderr, "Error: incorrect inception level\n"); + exit (EXIT_FAILURE); + } } else { inception_level = 2; } + printf ("Inception activated, level: %d\n", inception_level); break; case 'x': printf ("cross ai\n"); - cross_ai = true; + if ( optarg ) { + cross_ai = check_int_value(optarg, 0, 1); + if ( cross_ai == -1 ) { + fprintf(stderr, "Error: incorrect cross ai value\n"); + exit (EXIT_FAILURE); + } + } + else { + fprintf(stderr, "Error: you must specify a value for cross ai\n"); + exit (EXIT_FAILURE); + } + break; case 'o': printf ("round ai\n"); - round_ai = true; + if ( optarg ) { + round_ai = check_int_value(optarg, 0, 1); + if ( round_ai == -1 ) { + fprintf(stderr, "Error: incorrect round ai value\n"); + exit (EXIT_FAILURE); + } + } + else { + fprintf(stderr, "Error: you must specify a value for round ai\n"); + exit (EXIT_FAILURE); + } break; case 'c': @@ -72,6 +114,7 @@ int main(int argc, char* argv[]) { exit(EXIT_SUCCESS); default: + fprintf(stderr, "Error: unknown option"); exit (EXIT_FAILURE); } }