From: Trent Huber Date: Fri, 8 Nov 2024 23:38:12 +0000 (-0500) Subject: Clean up error messages X-Git-Url: https://trenthuber.com/code?a=commitdiff_plain;h=c8006494e60bfd4081f79c0b5d285d667f519db0;p=xpmview.git Clean up error messages - Line numbers added to all relevant error messages - Verbage changed to be both clearer for end users and more consistant with the XPM manual (found in ./resourses) --- diff --git a/src/main.c b/src/main.c index 620313d..0c4d3f4 100644 --- a/src/main.c +++ b/src/main.c @@ -40,7 +40,8 @@ int main(void) { } if (IsKeyPressed(KEY_S) && have_texture) { char png_file_path[FILE_PATH_CAP] = {0}; - strncpy(png_file_path, xpm_file_path, strlen(xpm_file_path) - strlen(".xpm")); + strncpy(png_file_path, xpm_file_path, + strlen(xpm_file_path) - strlen(".xpm")); strncat(png_file_path, ".png", strlen(".png")); ExportImage(image, png_file_path); } @@ -54,8 +55,10 @@ int main(void) { float scale = screen_width * texture.height > screen_height * texture.width ? (float)screen_height / texture.height : (float)screen_width / texture.width; - Vector2 position = CLITERAL(Vector2){(screen_width - (texture.width * scale)) / 2, - (screen_height - (texture.height * scale)) / 2}; + Vector2 position = CLITERAL(Vector2){ + (screen_width - (texture.width * scale)) / 2, + (screen_height - (texture.height * scale)) / 2 + }; DrawTextureEx(texture, position, 0, scale, WHITE); } else { const char *message = startup ? "Drag and drop an XPM file here" diff --git a/src/parser.c b/src/parser.c index 8eccdde..0e9b2e5 100644 --- a/src/parser.c +++ b/src/parser.c @@ -17,10 +17,9 @@ unsigned int *pixels; bool parse_xpm_file(Image *image, const char *file_path) { line_number = 0; - switch (sigsetjmp(env, 0)) { + switch (sigsetjmp(env, 0)) case 1: return false; - } if ((file = fopen(file_path, "r")) == NULL) SIMPLE_XPM_ERROR("Unable to open provided file"); @@ -31,12 +30,14 @@ bool parse_xpm_file(Image *image, const char *file_path) { char *line_buffer_p = line_buffer; check_next_token(&line_buffer_p, "static"); if (!isspace(*line_buffer_p)) - SIMPLE_XPM_ERROR("Expected token \"static\""); + SIMPLE_XPM_ERROR("The word `static' at line %d lacks trailing whitespace", + line_number); check_next_token(&line_buffer_p, "char"); check_next_token(&line_buffer_p, "*"); if (isdigit(strstrip(&line_buffer_p)[0])) - SIMPLE_XPM_ERROR("Incorrect C variable name"); + SIMPLE_XPM_ERROR("Invalid name for array at line %d (must be a valid C " + "variable name)", line_number); for (; strlen(line_buffer_p) != 0 && (isalnum(*line_buffer_p) || *line_buffer_p == '_'); ++line_buffer_p); check_next_token(&line_buffer_p, "["); @@ -61,17 +62,23 @@ bool parse_xpm_file(Image *image, const char *file_path) { xpm_ext_token = NULL; if (!get_terminal_token(&line_buffer_p, &y_hotspot_token)) { if (!get_terminal_token(&line_buffer_p, &xpm_ext_token)) - SIMPLE_XPM_ERROR("Too many arguments for values"); - else if (strncmp(xpm_ext_token, "XPMEXT", strlen("XPMEXT")) != 0) - SIMPLE_XPM_ERROR("XPMEXT value not set correctly"); + SIMPLE_XPM_ERROR("The values section contains too many words"); + else if (strlen(xpm_ext_token) != strlen("XPMEXT") + || strncmp(xpm_ext_token, "XPMEXT", strlen("XPMEXT")) != 0) + SIMPLE_XPM_ERROR("The \"XPMEXT\" value should be set to `XPMEXT' if XPM " + "extensions are desired, else no tag should be " + "specified (line %d)", line_number); } - } else if (strncmp(xpm_ext_token, "XPMEXT", strlen("XPMEXT")) != 0) - SIMPLE_XPM_ERROR("Must specify y_hotspot alongside x_hotspot"); + } else if (strlen(xpm_ext_token) != strlen("XPMEXT") + || strncmp(xpm_ext_token, "XPMEXT", strlen("XPMEXT")) != 0) + SIMPLE_XPM_ERROR("Can't specify a value for \"x_hotspot\" without a value " + "for \"y_hotspot\" (line %d)", line_number); } size_t chars_per_pixel = convert_token_to_num(chars_per_pixel_token, 10); if (width == 0 || height == 0 || num_colors == 0 || chars_per_pixel == 0) - SIMPLE_XPM_ERROR("Invalid values token"); + SIMPLE_XPM_ERROR("One of the values on line %d is zero; make sure all values " + "are positive integers", line_number); // TODO: Hotspots are not implemented ssize_t x_hotspot = x_hotspot_token ? convert_token_to_num(x_hotspot_token, 10) : -1; @@ -94,11 +101,14 @@ bool parse_xpm_file(Image *image, const char *file_path) { check_next_token(&line_buffer_p, "\""); if (strlen(line_buffer_p) < chars_per_pixel) - SIMPLE_XPM_ERROR("Unable to parse color line"); + SIMPLE_XPM_ERROR("Line %d in the color section contains too few characters " + "to be properly parsed", line_number); strncpy(&keys[i * chars_per_pixel], line_buffer_p, chars_per_pixel); line_buffer_p += chars_per_pixel; if (*line_buffer_p != '\t' && *line_buffer_p != ' ') - SIMPLE_XPM_ERROR("Incorrect whitespace in color line"); + SIMPLE_XPM_ERROR("Words must be separated by tabs and/or spaces; line %d " + "contains nonstandard whitespace after the first word", + line_number); *line_buffer_p++ = '\0'; bool is_last_token; @@ -112,8 +122,14 @@ bool parse_xpm_file(Image *image, const char *file_path) { switch(*color_str) { case '#':; // RGB size_t hex_value = convert_token_to_num(++color_str, 16); - if (hex_value> 0xffffff) - SIMPLE_XPM_ERROR("Hex #%s is not a valid color value", color_str); + if (hex_value > 0xffffff) { + if (strlen(color_str)) + SIMPLE_XPM_ERROR("Hex value `#%s' on line %d is not a valid color value", + color_str, line_number); + else + SIMPLE_XPM_ERROR("Empty hex value on line %d is not a valid color value", + line_number); + } size_t r = (hex_value & 0x00ff0000) >> (2 * 8), g = (hex_value & 0x0000ff00), b = (hex_value & 0x000000ff) << (2 * 8), @@ -122,11 +138,13 @@ bool parse_xpm_file(Image *image, const char *file_path) { break; case '%':; // HSV // TODO: Parse %HSV codes - SIMPLE_XPM_ERROR("HSV values not implemented yet"); + SIMPLE_XPM_ERROR("Parsing HSV values is not implemented yet (line %d)", + line_number); default:; // "Colornames" // TODO: Parse colornames // https://en.wikipedia.org/wiki/X11_color_names#Color_name_chart - SIMPLE_XPM_ERROR("Colorname values not implemented yet"); + SIMPLE_XPM_ERROR("Parsing colorname values is not implemented yet " + "(line %d)", line_number); } color_table[mode * num_colors + i] = color; } while(!is_last_token); @@ -135,7 +153,8 @@ bool parse_xpm_file(Image *image, const char *file_path) { // TODO: Be able to dynamically change modes Xpm_Mode current_mode = XPM_MODE_COLOR; if (!possible_modes[current_mode]) - SIMPLE_XPM_ERROR("Current mode not supported"); + SIMPLE_XPM_ERROR("Color visual mode is the only mode currently supported " + "(line %d)", line_number); // Parse array of pixel values SIMPLE_XPM_FREE(pixels); // Need to have the pixels still exist even when this function exits @@ -147,7 +166,8 @@ bool parse_xpm_file(Image *image, const char *file_path) { line_buffer_p = line_buffer; check_next_token(&line_buffer_p, "\""); if (strlen(line_buffer_p) < width * chars_per_pixel + strlen("\",")) - SIMPLE_XPM_ERROR("String in pixels section is formatted improperly"); + SIMPLE_XPM_ERROR("Line %d in pixels sections contains too few characters to " + "be properly parsed", line_number); for (size_t j = 0; j < width; ++j) { for (size_t k = 0; k < chars_per_pixel; ++k) { key_buffer[k] = *line_buffer_p++; @@ -158,8 +178,8 @@ bool parse_xpm_file(Image *image, const char *file_path) { } } } - if (*line_buffer_p++ != '"') - SIMPLE_XPM_ERROR("Pixels section is not formatted correctly"); + if (*line_buffer_p++ != '"') // Needs to be done manually for whitespace + SIMPLE_XPM_ERROR("Expected a `\"' at the end of line %d", line_number); check_next_token(&line_buffer_p, ","); } SIMPLE_XPM_FREE(key_buffer); @@ -168,7 +188,7 @@ bool parse_xpm_file(Image *image, const char *file_path) { // TODO: Extensions are not implemented if (xpm_ext) { - printf("Parsing XPM extensions\n"); + fprintf(stdout, "simplexpm: INFO: Parsing XPM extensions\n"); } get_next_line_check_eof(&line_buffer, file); @@ -176,11 +196,13 @@ bool parse_xpm_file(Image *image, const char *file_path) { check_next_token(&line_buffer_p, "}"); check_next_token(&line_buffer_p, ";"); if (*strstrip(&line_buffer_p) != '\0') - SIMPLE_XPM_ERROR("File can't have elements after array declaration"); + SIMPLE_XPM_ERROR("Trailing elements on line %d after the array aren't " + "allowed", line_number); while (get_next_line(&line_buffer, file)) { line_buffer_p = line_buffer; if (*strstrip(&line_buffer_p) != '\0') - SIMPLE_XPM_ERROR("File can't have elements after array declaration"); + SIMPLE_XPM_ERROR("Trailing elements on line %d after the array aren't " + "allowed", line_number); } fclose(file); SIMPLE_XPM_FREE(line_buffer); diff --git a/src/tokenizer.c b/src/tokenizer.c index 06c2caa..065e8d9 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -67,7 +67,7 @@ void get_next_line_check_eof(char **buffer, FILE *file) { void check_next_token(char **string, const char *token) { size_t token_len = strlen(token); if (strncmp(strstrip(string), token, token_len) != 0) - SIMPLE_XPM_ERROR("Expected \"%s\" at line %d", token, line_number); + SIMPLE_XPM_ERROR("Expected the word `%s' at line %d", token, line_number); *string += token_len; } @@ -87,14 +87,15 @@ void check_xpm_header(FILE *file) { char *get_next_token(char **string) { char *result; - do { + do if ((result = strsep(string, "\t ")) == NULL) - SIMPLE_XPM_ERROR("Couldn't parse expected next token"); - } while (*result == '\0'); - if (*string == NULL) - SIMPLE_XPM_ERROR("Did not expect next token to be a terminal token"); + SIMPLE_XPM_ERROR("Unable to parse expected token on line %d", line_number); + while (*result == '\0'); + if (*string == NULL) // This function doesn't expect terminal tokens + SIMPLE_XPM_ERROR("Missing words on line %d", line_number); if (strlen(result) != strlen(strstrip(&result))) - SIMPLE_XPM_ERROR("Weird whitespace characters between array tokens"); + SIMPLE_XPM_ERROR("Words must be separated by tabs and/or spaces; line %d " + "contains nonstandard whitespace", line_number); return result; } @@ -111,7 +112,7 @@ bool get_terminal_token(char **string, char **token) { } *(*string)++ = '\0'; if (*token == *string) - SIMPLE_XPM_ERROR("Couldn't parse potential last token"); + SIMPLE_XPM_ERROR("Missing last word on line %d", line_number); while (**string == '\t' || **string == ' ') ++*string; if (**string != '"') { result = false; @@ -123,17 +124,24 @@ check_comma: defer: if (strlen(*token) != strlen(strstrip(token))) - SIMPLE_XPM_ERROR("Weird whitespace characters between array tokens"); + SIMPLE_XPM_ERROR("Words must be separated by tabs and/or spaces; line %d " + "contains nonstandard whitespace", line_number); return result; } size_t convert_token_to_num(const char *token, int base) { if (token == NULL) - SIMPLE_XPM_ERROR("Expected non-null token to parse"); + SIMPLE_XPM_ERROR("Unable to parse empty word from line %d", line_number); errno = 0; char *end_p; long result = strtol(token, &end_p, base); - if (*end_p != '\0' || errno == ERANGE || result < 0) - SIMPLE_XPM_ERROR("\"%s\" is not a valid number", token); + if (*end_p != '\0' || errno == ERANGE || result < 0) { + if (strlen(token) == 0) + SIMPLE_XPM_ERROR("Unable to parse an empty word from line %d as a number", + line_number); + else + SIMPLE_XPM_ERROR("Word `%s' from line %d is not a valid number", + token, line_number); + } return (size_t)result; } diff --git a/src/utils.h b/src/utils.h index d247be6..6fee983 100644 --- a/src/utils.h +++ b/src/utils.h @@ -11,7 +11,7 @@ do { \ p = malloc(size); \ if (p == NULL) { \ - fprintf(stderr, "simplexpm: OUT OF MEMORY: Terminating\n"); \ + fprintf(stderr, "simplexpm: OUT OF MEMORY: Terminating process\n"); \ exit(EXIT_FAILURE); \ } \ memset(p, 0, size); \ @@ -33,8 +33,7 @@ extern unsigned int line_number; SIMPLE_XPM_FREE(keys); \ SIMPLE_XPM_FREE(color_table); \ SIMPLE_XPM_FREE(pixels); \ - fprintf(stderr, "simplexpm: ERROR: "); \ - fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "simplexpm: ERROR: " __VA_ARGS__); \ fprintf(stderr, "\n"); \ siglongjmp(env, 1); \ } while (0)