diff --git a/src/Makefile b/src/Makefile index cecdfec8e930024ed8af43d67bc0e470ad26d462..4e5c1846dc379dde135145ebf9bb5e5b63a100a6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -32,6 +32,7 @@ prompt.o: prompt.c prompt.h helper.h clean: -rm -f *.o -rm -f $(TARGET) + -rm -f ./log/*.txt # Advanced memory usage stats as well as crash reporting. valgrind: $(TARGET) diff --git a/src/helper.c b/src/helper.c index f9a285dcf2b2a9d775281c448852d9dde2f976ff..22913eb545e13e73cbc218f105dc309a82b54804 100644 --- a/src/helper.c +++ b/src/helper.c @@ -11,12 +11,12 @@ /** - * Same arguments as calloc, but calls perror() on error and exits. + * Same arguments as calloc, but calls log_error on error and exits. */ void *calloc_or_quit(size_t nmemb, size_t size) { void *ptr = calloc(nmemb, size); if (ptr == NULL) { - perror("Failed to allocate memory"); + log_error(1, "%s", "Failed to allocate memory."); exit(1); } @@ -25,10 +25,10 @@ void *calloc_or_quit(size_t nmemb, size_t size) { /** - * Prints out error message and exits program with error code of 1. + * Logs error message and exits program with error code of 1. */ void code_error_quit(const char *message) { - printf("ERROR: %s\n", message); + log_error(1, "%s", message); exit(1); } @@ -37,7 +37,7 @@ void code_error_quit(const char *message) { * Wrapper function for info message logging. * Calls appropriate logging sub-functions. */ -void va_log_info(const char *s_file_name, int s_line_num, const char *s_format_string, ...) { +void va_log_info(int log_mode, const char *s_file_name, int s_line_num, const char *s_format_string, ...) { char *log_level = "INFO"; time_t rawtime; struct tm * timeinfo; @@ -48,15 +48,22 @@ void va_log_info(const char *s_file_name, int s_line_num, const char *s_format_s timeinfo = localtime ( &rawtime ); // Call appropriate logging sub-fucntions and handle variable length arg input. - // To console. - va_start(va_arglist, s_format_string); - va_to_console(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); - va_end(va_arglist); - - // To info file. - va_start(va_arglist, s_format_string); - va_to_info_file(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); - va_end(va_arglist); + // Check if logging is enabled. + if (log_mode) { + // To console. + va_start(va_arglist, s_format_string); + va_log_to_console(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); + va_end(va_arglist); + // To info file. + va_start(va_arglist, s_format_string); + va_to_info_file(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); + va_end(va_arglist); + } else { + // To console. + va_start(va_arglist, s_format_string); + va_print_to_console(s_format_string, va_arglist); + va_end(va_arglist); + } } @@ -64,7 +71,7 @@ void va_log_info(const char *s_file_name, int s_line_num, const char *s_format_s * Wrapper function for warn message logging. * Calls appropriate logging sub-functions. */ -void va_log_warn(const char *s_file_name, int s_line_num, const char *s_format_string, ...) { +void va_log_warn(int log_mode, const char *s_file_name, int s_line_num, const char *s_format_string, ...) { char *log_level = "WARN"; time_t rawtime; struct tm * timeinfo; @@ -75,20 +82,28 @@ void va_log_warn(const char *s_file_name, int s_line_num, const char *s_format_s timeinfo = localtime ( &rawtime ); // Call appropriate logging sub-fucntions and handle variable length arg input. - // To console. - va_start(va_arglist, s_format_string); - va_to_console(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); - va_end(va_arglist); - - // To info file. - va_start(va_arglist, s_format_string); - va_to_info_file(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); - va_end(va_arglist); - - // To warn file. - va_start(va_arglist, s_format_string); - va_to_warn_file(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); - va_end(va_arglist); + // Check if logging is enabled. + if (log_mode) { + // To console. + va_start(va_arglist, s_format_string); + va_log_to_console(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); + va_end(va_arglist); + + // To info file. + va_start(va_arglist, s_format_string); + va_to_info_file(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); + va_end(va_arglist); + + // To warn file. + va_start(va_arglist, s_format_string); + va_to_warn_file(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); + va_end(va_arglist); + } else { + // To console. + va_start(va_arglist, s_format_string); + va_print_to_console(s_format_string, va_arglist); + va_end(va_arglist); + } } @@ -96,7 +111,7 @@ void va_log_warn(const char *s_file_name, int s_line_num, const char *s_format_s * Wrapper function for error message logging. * Calls appropriate logging sub-functions. */ -void va_log_error(const char *s_file_name, int s_line_num, const char *s_format_string, ...) { +void va_log_error(int log_mode, const char *s_file_name, int s_line_num, const char *s_format_string, ...) { char *log_level = "ERROR"; time_t rawtime; struct tm * timeinfo; @@ -107,32 +122,60 @@ void va_log_error(const char *s_file_name, int s_line_num, const char *s_format_ timeinfo = localtime ( &rawtime ); // Call appropriate logging sub-fucntions and handle variable length arg input. - // To console. - va_start(va_arglist, s_format_string); - va_to_console(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); - va_end(va_arglist); - - // To info file. - va_start(va_arglist, s_format_string); - va_to_info_file(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); - va_end(va_arglist); - - // To warn file. - va_start(va_arglist, s_format_string); - va_to_warn_file(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); - va_end(va_arglist); - - // To error file. - va_start(va_arglist, s_format_string); - va_to_error_file(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); - va_end(va_arglist); + // Check if logging is enabled. + if (log_mode) { + // To console. + va_start(va_arglist, s_format_string); + va_log_to_console(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); + va_end(va_arglist); + + // To info file. + va_start(va_arglist, s_format_string); + va_to_info_file(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); + va_end(va_arglist); + + // To warn file. + va_start(va_arglist, s_format_string); + va_to_warn_file(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); + va_end(va_arglist); + + // To error file. + va_start(va_arglist, s_format_string); + va_to_error_file(__FILE__, __LINE__, log_level, timeinfo, s_format_string, va_arglist); + va_end(va_arglist); + } else { + // To console. + va_start(va_arglist, s_format_string); + va_print_to_console(s_format_string, va_arglist); + va_end(va_arglist); + } +} + + +/** + * Print variable length message to console. + * Does not have datetime or source file information. + */ +void va_print_to_console(const char *s_format_string, va_list va_arglist) { + + char *format_string; + + // Create formatted string, with default formatting. + format_string = calloc(MAX_LOG_STRING_LENGTH, sizeof(char*)); + sprintf(format_string, "%s\n", s_format_string); + + // Print to console. + vprintf(format_string, va_arglist); + + // Clean up. + free(format_string); } /** * Log variable length message to console. */ -void va_to_console(const char *s_file_name, +void va_log_to_console(const char *s_file_name, int s_line_num, const char *log_level, struct tm * timeinfo, diff --git a/src/helper.h b/src/helper.h index 1f4934bfb0b70a4f0bb8b5fb48994fa1f7d3dcce..d0188c9ba7c02f2f3d06a39d3d18589a537999fc 100644 --- a/src/helper.h +++ b/src/helper.h @@ -26,12 +26,12 @@ // Function Prototypes. void *calloc_or_quit(size_t nmemb, size_t size); void code_error_quit(const char *message); -void va_log_print(const char *s_file_name, int s_line_num, const char *s_format_string, ...); -void va_log_info(const char *s_file_name, int s_line_num, const char *s_format_string, ...); -void va_log_warn(const char *s_file_name, int s_line_num, const char *s_format_string, ...); -void va_log_error(const char *s_file_name, int s_line_num, const char *s_format_string, ...); +void va_log_info(int log_mode, const char *s_file_name, int s_line_num, const char *s_format_string, ...); +void va_log_warn(int log_mode, const char *s_file_name, int s_line_num, const char *s_format_string, ...); +void va_log_error(int log_mode, const char *s_file_name, int s_line_num, const char *s_format_string, ...); +void va_print_to_console(const char *s_format_string, va_list va_arglist); -void va_to_console(const char *s_file_name, +void va_log_to_console(const char *s_file_name, int s_line_num, const char *log_level, struct tm * timeinfo, @@ -61,11 +61,11 @@ void va_to_error_file(const char *s_file_name, // Macro definitions. -#define log_info(s_format_string, ...) \ - va_log_info(__FILE__, __LINE__, s_format_string, __VA_ARGS__) +#define log_info(log_mode, s_format_string, ...) \ + va_log_info(log_mode, __FILE__, __LINE__, s_format_string, __VA_ARGS__) -#define log_warn(s_format_string, ...) \ - va_log_warn(__FILE__, __LINE__, s_format_string, __VA_ARGS__) +#define log_warn(log_mode, s_format_string, ...) \ + va_log_warn(log_mode, __FILE__, __LINE__, s_format_string, __VA_ARGS__) -#define log_error(s_format_string, ...) \ - va_log_error(__FILE__, __LINE__, s_format_string, __VA_ARGS__) +#define log_error(log_mode, s_format_string, ...) \ + va_log_error(log_mode, __FILE__, __LINE__, s_format_string, __VA_ARGS__) diff --git a/src/main.c b/src/main.c index ce43aef6001aec5d8a40b4a0f8939c8324def4bb..f1d6e672a00291f47a503d899ba48731d199010b 100644 --- a/src/main.c +++ b/src/main.c @@ -26,9 +26,9 @@ // Method Declaration. -void run_quad_solver(); -void exit_program(); +void run_quad_solver(double a, double b, double c, int logging_mode); char parse_doubles(const char *string, double *a, double *b, double *c); +void exit_program(int exit_code, int logging_mode); /** @@ -55,12 +55,12 @@ int main(int argc, char* argv[]) { // logging option ARGKEY arg_logging = argparse_add_argument( argparse, "--log", "-l", "Enable logging mode.", 0); - char logging_mode = 0; // TODO: Use this logging flag in our code + char logging_mode = 0; // test input 3 numbers with flag ARGKEY arg_nums = argparse_add_argument( argparse, "--nums", "-n", "Accepts three numbers 'A B C'. See NUM_FORMAT", 3); - char nums_set = 0; + int nums_set = 0; char parse_errors = argparse_parse(argparse, argc, argv); if (parse_errors == 0) { @@ -70,7 +70,7 @@ int main(int argc, char* argv[]) { logging_mode = argparse_get_argument(argparse, arg_logging, NULL, NULL); if (logging_mode) { - printf("TODO: Do logging!\n"); + log_info(logging_mode, "%s", "Logging is enabled."); } double a = 0; @@ -84,59 +84,59 @@ int main(int argc, char* argv[]) { c = strtod(string_nums[2], NULL); } else { // Need to prompt for A B C - char *input_string = prompt_user("Please enter A B C.", NULL, 255); + char *input_string = prompt_user("Please enter A B C.", NULL, 255, logging_mode); if (parse_doubles(input_string, &a, &b, &c) != 0) { - fprintf(stderr, "Unexpected number format. Please use 'A B C'\n"); - exit(1); + log_error(logging_mode, "%s", "Unexpected number format. Please use 'A B C'"); + exit_program(1, logging_mode); } free(input_string); } - printf("Received floats:\nA: %.10E\nB: %.10E\nC: %.10E\n", a, b, c); + log_info(logging_mode, "Received floats:\nA: %.10E\nB: %.10E\nC: %.10E", a, b, c); // Check for valid args. if (a == 0) { // Invalid args provided. Exiting. - printf("Recieved %fx^2 + %fx + %f. Invalid equation, A can't be zero.\n", a, b, c); - printf("Note that non-integer values are parsed as \"0\".\n"); - printf("Please try again.\n"); + log_warn(logging_mode, "Recieved %fx^2 + %fx + %f. Invalid equation, A can't be zero.", a, b, c); + log_warn(logging_mode, "%s", "Note that non-integer values are parsed as \"0\"."); + log_warn(logging_mode, "%s", "Please try again."); // a, b, c > 0 or NAN } else if ((a > 0 && (a < FLT_MIN || a > FLT_MAX)) || isnan(a)) { - printf("The first value is not within the exclusive range %.10e - %.10e\n", FLT_MIN, FLT_MAX); - printf("Please try again.\n"); + log_warn(logging_mode, "The first value is not within the exclusive range %.10e - %.10e", FLT_MIN, FLT_MAX); + log_warn(logging_mode, "%s", "Please try again."); } else if ((b > 0 && (b < FLT_MIN || b > FLT_MAX)) || isnan(b)) { - printf("The second value is not within the exclusive range %.10e - %.10e\n", FLT_MIN, FLT_MAX); - printf("Please try again.\n"); + log_warn(logging_mode, "The second value is not within the exclusive range %.10e - %.10e", FLT_MIN, FLT_MAX); + log_warn(logging_mode, "%s", "Please try again."); } else if ((c > 0 && (c < FLT_MIN || c > FLT_MAX)) || isnan(c)) { - printf("The last value is not within the exclusive range %.10e - %.10e\n", FLT_MIN, FLT_MAX); - printf("Please try again.\n"); + log_warn(logging_mode, "The last value is not within the exclusive range %.10e - %.10e", FLT_MIN, FLT_MAX); + log_warn(logging_mode, "%s", "Please try again."); // a, b, c < 0 } else if (a < 0 && (a < -FLT_MAX || a > -FLT_MIN)) { - printf("The first value is not within the exclusive range %.10e - %.10e\n", -FLT_MAX, -FLT_MIN); - printf("Please try again.\n"); + log_warn(logging_mode, "The first value is not within the exclusive range %.10e - %.10e", -FLT_MAX, -FLT_MIN); + log_warn(logging_mode, "%s", "Please try again."); } else if (b < 0 && (b < -FLT_MAX || b > -FLT_MIN)) { - printf("The second value is not within the exclusive range %.10e - %.10e\n", -FLT_MAX, -FLT_MIN); - printf("Please try again.\n"); + log_warn(logging_mode, "The second value is not within the exclusive range %.10e - %.10e", -FLT_MAX, -FLT_MIN); + log_warn(logging_mode, "%s", "Please try again."); } else if (c < 0 && (c < -FLT_MAX || c > -FLT_MIN)) { - printf("The last value is not within the exclusive range %.10e - %.10e\n", -FLT_MAX, -FLT_MIN); - printf("Please try again.\n"); + log_warn(logging_mode, "The last value is not within the exclusive range %.10e - %.10e", -FLT_MAX, -FLT_MIN); + log_warn(logging_mode, "%s", "Please try again."); } else { // Values are valid. Execute solver. - run_quad_solver(a, b, c); + run_quad_solver(a, b, c, logging_mode); exit_code = 0; } } argparse_free(argparse); - exit_program(exit_code); + exit_program(exit_code, logging_mode); } /** * Runs the quad solver equation and outputs results. */ -void run_quad_solver(double a, double b, double c) { - printf("Calculating %.01Ex^2 + %.01Ex + %.01E = 0.\n", a, b, c); +void run_quad_solver(double a, double b, double c, int logging_mode) { + log_info(logging_mode, "Calculating %.01Ex^2 + %.01Ex + %.01E = 0.", a, b, c); COMPUTATION_STRUCT *root1; COMPUTATION_STRUCT *root2; @@ -149,7 +149,7 @@ void run_quad_solver(double a, double b, double c) { round_error = "Yes"; } - printf("Results:\n\tr1: %s\n\n\tr2: %s\n\n\tInexact: %s\n", + log_info(logging_mode, "Results:\n\tr1: %s\n\n\tr2: %s\n\n\tInexact: %s", root1->x_as_string, root2->x_as_string, round_error); computation_struct_free(root1); @@ -215,7 +215,13 @@ char parse_doubles(const char *string, double *a, double *b, double *c) { /** * Handles program exit and cleanup. */ -void exit_program(int exit_code) { - printf("\nExiting program with code of %d.\n", exit_code); +void exit_program(int exit_code, int logging_mode) { + // Check if code is non-zero. If so, log as error. Else log as info. + printf("\n"); + if (exit_code) { + log_error(logging_mode, "Exiting program with code of %d.", exit_code); + } else { + log_info(logging_mode, "Exiting program with code of %d.", exit_code); + } exit(exit_code); } diff --git a/src/prompt.c b/src/prompt.c index b77d61308dcabe5c1d275e02bf9fd3702dca33b2..e438436eb39cf6e222388468c4470bb918b0e388 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -27,10 +27,10 @@ * What is your name? * : _ */ -char *prompt_user(char *text, char *options, size_t size) { - printf("%s\n", text); +char *prompt_user(char *text, char *options, size_t size, int logging_mode) { + log_info(logging_mode, "%s", text); if (options) { - printf("%s", options); + log_info(logging_mode, "%s", options); } printf(": "); char *buffer = calloc_or_quit(size, 1); diff --git a/src/prompt.h b/src/prompt.h index e6a3bf6d045a4ac21dae1ecc0fe656ad44e8f669..ef2dcb5930c6849ff6f64ae7244c9328f21a5190 100644 --- a/src/prompt.h +++ b/src/prompt.h @@ -9,4 +9,4 @@ // Function Prototypes. -char *prompt_user(char *text, char *options, size_t size); +char *prompt_user(char *text, char *options, size_t size, int logging_mode);