| summaryrefslogtreecommitdiff |
diff options
Diffstat (limited to 'src/cli')
| -rw-r--r-- | src/cli/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | src/cli/cli.h | 145 | ||||
| -rw-r--r-- | src/cli/parameters.c | 385 | ||||
| -rw-r--r-- | src/cli/parameters.h | 13 | ||||
| -rw-r--r-- | src/cli/parameters_types.h | 67 |
5 files changed, 616 insertions, 0 deletions
diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt new file mode 100644 index 0000000..94e6337 --- /dev/null +++ b/src/cli/CMakeLists.txt @@ -0,0 +1,6 @@ +set( + SRC_FILES ${SRC_FILES} + ${CMAKE_CURRENT_SOURCE_DIR}/parameters.c +) +set(SRC_FILES ${SRC_FILES} PARENT_SCOPE) + diff --git a/src/cli/cli.h b/src/cli/cli.h new file mode 100644 index 0000000..5aec25b --- /dev/null +++ b/src/cli/cli.h @@ -0,0 +1,145 @@ +#ifndef _ZoO_CLI_CLI_H_ +#define _ZoO_CLI_CLI_H_ + +#include <stdio.h> + +#include "../pervasive.h" + + +#ifndef ZoO_DEBUG_PROGRAM_FLOW + #define ZoO_DEBUG_PROGRAM_FLOW (0 || ZoO_DEBUG_ALL) +#endif + +#ifndef ZoO_DEBUG_CONFIG + #define ZoO_DEBUG_CONFIG (0 || ZoO_DEBUG_ALL) +#endif + +#ifndef ZoO_DEBUG_LEARNING + #define ZoO_DEBUG_LEARNING (0 || ZoO_DEBUG_ALL) +#endif + +#ifndef ZoO_DEBUG_NETWORK + #define ZoO_DEBUG_NETWORK 1 +#endif + +#ifndef ZoO_DEBUG_NETWORK + #define ZoO_DEBUG_NETWORK (0 || ZoO_DEBUG_ALL) +#endif + +#define ZoO_ENABLE_WARNINGS_OUTPUT 1 +#define ZoO_ENABLE_RUNTIME_ERRORS_OUTPUT 1 +#define ZoO_ENABLE_PROGRAMMING_ERRORS_OUTPUT 1 +#define ZoO_ENABLE_FATAL_ERROR_OUTPUT 1 + +#ifdef ZoO_ENABLE_ERROR_LOCATION + #define ZoO_LOCATION "[" __FILE__ "][" ZoO_TO_STRING(__LINE__) "]" +#else + #define ZoO_LOCATION "" +#endif + +#define ZoO_PRINT_STDERR(symbol, str, ...)\ + fprintf(stderr, "[" symbol "]" ZoO_LOCATION " " str "\n", __VA_ARGS__); + +/* + * Given that we use preprocessor contants as flags, we can expect the compilers + * to remove the test condition for disabled flags. No need to be shy about + * allowing many debug options. + */ + +#define ZoO_DEBUG(flag, str, ...)\ + ZoO_ISOLATE\ + (\ + if (flag)\ + {\ + ZoO_PRINT_STDERR("D", str, __VA_ARGS__);\ + }\ + ) + + +#define ZoO_WARNING(str, ...)\ + ZoO_ISOLATE\ + (\ + if (ZoO_ENABLE_WARNINGS_OUTPUT)\ + {\ + ZoO_PRINT_STDERR("W", str, __VA_ARGS__);\ + }\ + ) + +#define ZoO_ERROR(str, ...)\ + ZoO_ISOLATE\ + (\ + if (ZoO_ENABLE_RUNTIME_ERRORS_OUTPUT)\ + {\ + ZoO_PRINT_STDERR("E", str, __VA_ARGS__);\ + }\ + ) + +#define ZoO_PROG_ERROR(str, ...)\ + ZoO_ISOLATE\ + (\ + if (ZoO_ENABLE_PROGRAMMING_ERRORS_OUTPUT)\ + {\ + ZoO_PRINT_STDERR("P", str, __VA_ARGS__);\ + }\ + ) + +#define ZoO_FATAL(str, ...)\ + ZoO_ISOLATE\ + (\ + if (ZoO_ENABLE_FATAL_ERROR_OUTPUT)\ + {\ + ZoO_PRINT_STDERR("F", str, __VA_ARGS__);\ + }\ + ) + +/* For outputs without dynamic content (static). ******************************/ + +#define ZoO_PRINT_S_STDERR(symbol, str)\ + fprintf(stderr, "[" symbol "]" ZoO_LOCATION " " str "\n"); + +#define ZoO_S_DEBUG(flag, str)\ + ZoO_ISOLATE\ + (\ + if (flag)\ + {\ + ZoO_PRINT_S_STDERR("D", str);\ + }\ + ) + +#define ZoO_S_WARNING(str)\ + ZoO_ISOLATE\ + (\ + if (ZoO_ENABLE_WARNINGS_OUTPUT)\ + {\ + ZoO_PRINT_S_STDERR("W", str);\ + }\ + ) + +#define ZoO_S_ERROR(str)\ + ZoO_ISOLATE\ + (\ + if (ZoO_ENABLE_RUNTIME_ERRORS_OUTPUT)\ + {\ + ZoO_PRINT_S_STDERR("E", str);\ + }\ + ) + +#define ZoO_S_PROG_ERROR(str)\ + ZoO_ISOLATE\ + (\ + if (ZoO_ENABLE_PROGRAMMING_ERRORS_OUTPUT)\ + {\ + ZoO_PRINT_S_STDERR("P", str);\ + }\ + ) + +#define ZoO_S_FATAL(str)\ + ZoO_ISOLATE\ + (\ + if (ZoO_ENABLE_FATAL_ERROR_OUTPUT)\ + {\ + ZoO_PRINT_S_STDERR("F", str);\ + }\ + ) + +#endif diff --git a/src/cli/parameters.c b/src/cli/parameters.c new file mode 100644 index 0000000..77c33aa --- /dev/null +++ b/src/cli/parameters.c @@ -0,0 +1,385 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "../pervasive.h" + +#include "error.h" + +#include "parameters.h" + +static void load_default_parameters +( + struct ZoO_parameters param [const restrict static 1] +) +{ + param->data_filename = ZoO_DEFAULT_DATA_FILENAME; + param->new_data_filename = (char *) NULL; + + param->irc_server_addr = ZoO_DEFAULT_IRC_SERVER_ADDR; + param->irc_server_port = ZoO_DEFAULT_IRC_SERVER_PORT; + param->irc_server_channel = ZoO_DEFAULT_IRC_SERVER_CHANNEL; + param->irc_username = ZoO_DEFAULT_IRC_USERNAME; + param->irc_realname = ZoO_DEFAULT_IRC_REALNAME; + + param->reply_rate = ZoO_DEFAULT_REPLY_RATE; + + param->aliases_count = 0; + param->aliases = NULL; +} + +static void print_help (const char exec [const restrict static 1]) +{ + printf + ( + "Usage: %s [option_1 option_2 ...] NICKNAME [ALIAS_1 ALIAS_2 ...] \n" + "NICKNAME is used as the IRC nickname value.\n" + "If NICKNAME or any ALIAS is found in an event, the program will reply.\n" + "\nAvailable options:\n" + " [--data-filename | -df] FILENAME\n" + " Learn content from FILENAME before connecting.\n" + " Default: %s.\n" + " [--new-data-filename | -ndf] FILENAME\n" + " Store new data learned in FILENAME.\n" + " Default: value of the --data-filename param.\n" + " [--irc-server-addr | -isa] IRC_SERVER_ADDR\n" + " Connect to this server address.\n" + " Default: %s.\n" + " [--irc-server-port | -isp] IRC_SERVER_PORT\n" + " Connect to this server port.\n" + " Default: %s.\n" + " [--irc-server-channel | -isc] IRC_SERVER_CHANNEL\n" + " Connect to this server's channel.\n" + " Default: %s.\n" + " [--irc-username | -iu] USERNAME\n" + " Connect using this as 'username' (shown in WHOIS).\n" + " Default: %s.\n" + " [--irc-realname | -ir] REALNAME\n" + " Connect using this as 'realname' (shown in WHOIS).\n" + " Default: %s.\n" + " [--reply-rate | -rr] REPLY_RATE\n" + " Chance to reply to an event (integer, range [0, 100]).\n" + " Default: %d.\n", + exec, + ZoO_DEFAULT_DATA_FILENAME, + ZoO_DEFAULT_IRC_SERVER_ADDR, + ZoO_DEFAULT_IRC_SERVER_PORT, + ZoO_DEFAULT_IRC_SERVER_CHANNEL, + ZoO_DEFAULT_IRC_USERNAME, + ZoO_DEFAULT_IRC_REALNAME, + ZoO_DEFAULT_REPLY_RATE + ); +} + +static int parse_string_arg +( + const char * restrict dest [const restrict static 1], + int const i, + const char * restrict argv [const restrict static 1], + int const argc +) +{ + if (i == argc) + { + ZoO_FATAL + ( + "Missing value for parameter '%s'.", + /* Safe: i > 1 */ + argv[i - 1] + ); + + return -1; + } + + *dest = argv[i]; + + return 0; +} + +static int parse_integer_arg +( + int dest [const restrict static 1], + int const i, + const char * argv [const restrict static 1], + int const argc, + int const min_val, + int const max_val +) +{ + long int result; + char * endptr; + const int old_errno = errno; + + if (i == argc) + { + ZoO_FATAL + ( + "Missing value for parameter '%s'.", + /* Safe: i > 1 */ + argv[i - 1] + ); + + return -1; + } + + errno = 0; + + result = strtol(argv[i], &endptr, 10); + + if + ( + (errno != 0) + || ((*endptr) == '\n') + || (result < min_val) + || (result > max_val) + ) + { + ZoO_FATAL + ( + "Invalid or missing value for parameter '%s', accepted range is " + "[%d, %d] (integer).", + /* Safe: i > 1 */ + argv[i - 1], + min_val, + max_val + ); + + errno = old_errno; + + return -1; + } + + *dest = (int) result; + + errno = old_errno; + + return 0; +} + +int ZoO_parameters_initialize +( + struct ZoO_parameters param [const restrict static 1], + int const argc, + const char * argv [const restrict static argc] +) +{ + int i; + + load_default_parameters(param); + + for (i = 1; i < argc; ++i) + { + if + ( + (strcmp(argv[i], "--data-filename") == 0) + || (strcmp(argv[i], "-df") == 0) + ) + { + i += 1; + + if + ( + parse_string_arg + ( + &(param->data_filename), + i, + argv, + argc + ) < 0 + ) + { + return -1; + } + } + else if + ( + (strcmp(argv[i], "--new-data-filename") == 0) + || (strcmp(argv[i], "-ndf") == 0) + ) + { + i += 1; + + if + ( + parse_string_arg + ( + &(param->new_data_filename), + i, + argv, + argc + ) < 0 + ) + { + return -1; + } + } + else if + ( + (strcmp(argv[i], "--irc-server-addr") == 0) + || (strcmp(argv[i], "-isa") == 0) + ) + { + i += 1; + + if + ( + parse_string_arg + ( + &(param->irc_server_addr), + i, + argv, + argc + ) < 0 + ) + { + return -1; + } + } + else if + ( + (strcmp(argv[i], "--irc-server-port") == 0) + || (strcmp(argv[i], "-isp") == 0) + ) + { + i += 1; + + if + ( + parse_string_arg + ( + &(param->irc_server_port), + i, + argv, + argc + ) < 0 + ) + { + return -1; + } + } + else if + ( + (strcmp(argv[i], "--irc-server-channel") == 0) + || (strcmp(argv[i], "-isc") == 0) + ) + { + i += 1; + + if + ( + parse_string_arg + ( + &(param->irc_server_channel), + i, + argv, + argc + ) < 0 + ) + { + return -1; + } + } + else if + ( + (strcmp(argv[i], "--irc-username") == 0) + || (strcmp(argv[i], "-iu") == 0) + ) + { + i += 1; + + if + ( + parse_string_arg + ( + &(param->irc_username), + i, + argv, + argc + ) < 0 + ) + { + return -1; + } + } + else if + ( + (strcmp(argv[i], "--irc-realname") == 0) + || (strcmp(argv[i], "-in") == 0) + ) + { + i += 1; + + if + ( + parse_string_arg + ( + &(param->irc_realname), + i, + argv, + argc + ) < 0 + ) + { + return -1; + } + } + else if + ( + (strcmp(argv[i], "--reply-rate") == 0) + || (strcmp(argv[i], "-rr") == 0) + ) + { + i += 1; + + if + ( + parse_integer_arg + ( + &(param->reply_rate), + i, + argv, + argc, + 0, + 100 + ) < 0 + ) + { + return -1; + } + } + else if + ( + (strcmp(argv[i], "--help") == 0) + || (strcmp(argv[i], "-h") == 0) + ) + { + print_help(argv[0]); + + return 0; + } + else + { + break; + } + } + + if (i == argc) + { + ZoO_S_FATAL("Missing argument: NICKNAME"); + + print_help(argv[0]); + + return -1; + } + + param->aliases_count = (argc - i); + param->aliases = (argv + i); + + if (param->new_data_filename == (char *) NULL) + { + param->new_data_filename = param->data_filename; + } + + return 1; +} diff --git a/src/cli/parameters.h b/src/cli/parameters.h new file mode 100644 index 0000000..1011e2b --- /dev/null +++ b/src/cli/parameters.h @@ -0,0 +1,13 @@ +#ifndef _ZoO_IO_PARAMETERS_H_ +#define _ZoO_IO_PARAMETERS_H_ + +#include "parameters_types.h" + +int ZoO_parameters_initialize +( + struct ZoO_parameters param [const static 1], + int const argc, + const char * argv [const static argc] +); + +#endif diff --git a/src/cli/parameters_types.h b/src/cli/parameters_types.h new file mode 100644 index 0000000..15b5254 --- /dev/null +++ b/src/cli/parameters_types.h @@ -0,0 +1,67 @@ +#ifndef _ZoO_IO_PARAMETERS_TYPES_H_ +#define _ZoO_IO_PARAMETERS_TYPES_H_ + +#include "../pervasive.h" + +/******************************************************************************/ +/** DEFAULT VALUES ************************************************************/ +/******************************************************************************/ + +#ifndef ZoO_DEFAULT_DATA_FILENAME + #define ZoO_DEFAULT_DATA_FILENAME "./memory.txt" +#endif + +#ifndef ZoO_DEFAULT_IRC_SERVER_ADDR + #define ZoO_DEFAULT_IRC_SERVER_ADDR "irc.foonetic.net" +#endif + +#ifndef ZoO_DEFAULT_IRC_SERVER_PORT + #define ZoO_DEFAULT_IRC_SERVER_PORT "6667" +#endif + +#ifndef ZoO_DEFAULT_IRC_SERVER_CHANNEL + #define ZoO_DEFAULT_IRC_SERVER_CHANNEL "#theborghivemind" +#endif + +#ifndef ZoO_DEFAULT_IRC_USERNAME + #define ZoO_DEFAULT_IRC_USERNAME "zeroofone" +#endif + +#ifndef ZoO_DEFAULT_IRC_REALNAME + #define ZoO_DEFAULT_IRC_REALNAME "Zero of One (bot)" +#endif + +#ifndef ZoO_DEFAULT_REPLY_RATE + #define ZoO_DEFAULT_REPLY_RATE 8 +#endif + +/******************************************************************************/ +/** DEBUG LEVELS **************************************************************/ +/******************************************************************************/ + +#ifndef ZoO_DEBUG_PARAMETERS + #define ZoO_DEBUG_PARAMETERS (0 || ZoO_DEBUG_ALL) +#endif + +/******************************************************************************/ +/** FUNCTIONS *****************************************************************/ +/******************************************************************************/ + +struct ZoO_parameters +{ + const char * restrict data_filename; + const char * restrict new_data_filename; + + const char * restrict irc_server_addr; + const char * restrict irc_server_port; + const char * restrict irc_server_channel; + const char * restrict irc_username; + const char * restrict irc_realname; + + int reply_rate; + + int aliases_count; + const char * restrict * restrict aliases; +}; + +#endif |


