]> Trent Huber's Code - xpmview.git/commitdiff
Clean up error messages
authorTrent Huber <trentmhuber@gmail.com>
Fri, 8 Nov 2024 23:38:12 +0000 (18:38 -0500)
committerTrent Huber <trentmhuber@gmail.com>
Fri, 8 Nov 2024 23:38:12 +0000 (18:38 -0500)
 - 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)

src/main.c
src/parser.c
src/tokenizer.c
src/utils.h

index 620313d82dc56df14b0cac6fc11dcd3f77b700b7..0c4d3f42c84d9ea0cc995a2446da97e68b6ffcbf 100644 (file)
@@ -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"
index 8eccddeb5c04b4f2a99bd28c845f4e46bb6559ba..0e9b2e56852a8cd45680911cf6d42b75b133e0a0 100644 (file)
@@ -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);
index 06c2caa7fe4a46c56c94f58fbfc3438d4d02ff2b..065e8d9be82c3a588b8fcadf0fc8976b583e8795 100644 (file)
@@ -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;
 }
index d247be64181fe37725c0b5743873f6817e1a1089..6fee983f6aa8233eee991fe1d7a6e1d65c7df86c 100644 (file)
@@ -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)