From dd8a7a9568c090ae14ea146c1f6139e9c8ef8a09 Mon Sep 17 00:00:00 2001 From: Trent Huber Date: Thu, 10 Oct 2024 21:14:20 -0400 Subject: [PATCH] Split code into multiple files --- cbs.c | 44 +++++--- include/parser.h | 17 +++ include/tokenizer.h | 13 +++ include/utils.h | 43 ++++++++ include/xpm_mode.h | 15 +++ src/main.c | 63 +++++++++++ src/main.o | Bin 0 -> 2816 bytes src/{simplexpm.c => parser.c} | 194 +--------------------------------- src/parser.o | Bin 0 -> 15816 bytes src/tokenizer.c | 79 ++++++++++++++ src/tokenizer.o | Bin 0 -> 7728 bytes src/utils.c | 18 ++++ src/utils.o | Bin 0 -> 3112 bytes src/xpm_mode.c | 13 +++ src/xpm_mode.o | Bin 0 -> 1852 bytes 15 files changed, 294 insertions(+), 205 deletions(-) create mode 100644 include/parser.h create mode 100644 include/tokenizer.h create mode 100644 include/utils.h create mode 100644 include/xpm_mode.h create mode 100644 src/main.c create mode 100644 src/main.o rename src/{simplexpm.c => parser.c} (57%) create mode 100644 src/parser.o create mode 100644 src/tokenizer.c create mode 100644 src/tokenizer.o create mode 100644 src/utils.c create mode 100644 src/utils.o create mode 100644 src/xpm_mode.c create mode 100644 src/xpm_mode.o diff --git a/cbs.c b/cbs.c index 5d775ef..423187b 100644 --- a/cbs.c +++ b/cbs.c @@ -3,6 +3,17 @@ #include CBS_LIBRARY_PATH #define CC "cc" +#define CFLAGS "-Wall", "-Wextra", "-Wpedantic" +#ifdef __MACH__ +#define LDFLAGS "-L./external/raylib/lib", "-lraylib", \ + "-framework", "CoreVideo", \ + "-framework", "IOKit", \ + "-framework", "Cocoa", \ + "-framework", "GLUT", \ + "-framework", "OpenGL" +#else +#define LDFLAGS "-L./external/raylib/lib", "-lraylib" +#endif // __MACH__ int main(int argc, char **argv) { cbs_rebuild_self(argv); @@ -12,20 +23,25 @@ int main(int argc, char **argv) { cbs_subbuild("./external"); cbs_run("mkdir", "-p", "./bin"); -#ifdef __MACH__ - cbs_run(CC, "-Wall", "-Wextra", "-Wpedantic", - "-I./external/raylib/src", - "-o", "./bin/simplexpm", - "./src/simplexpm.c", - "-L./external/raylib/lib", - "-lraylib", - "-framework", "CoreVideo", - "-framework", "IOKit", - "-framework", "Cocoa", - "-framework", "GLUT", - "-framework", "OpenGL"); -#endif // __MACH__ - cbs_run("./bin/simplexpm"); + Cbs_File_Paths src_files = {0}; + cbs_file_paths_build_file_ext(&src_files, "./src", ".c"); + cbs_file_paths_for_each (src_file, src_files) { + const char *obj_file = cbs_string_build(cbs_strip_file_ext(src_file), ".o"); + if (cbs_needs_rebuild(obj_file, src_file)) + cbs_run(CC, CFLAGS, "-c", "-I./include", "-I./external/raylib/src", + "-I./external/stb", "-o", obj_file, src_file); + } + + Cbs_File_Paths obj_files = {0}; + cbs_file_paths_build_file_ext(&obj_files, "./src", ".o"); + const char *bin_file = "./bin/simplexpm"; + Cbs_Cmd cmd = {0}; + cbs_cmd_build(&cmd, CC, "-o", bin_file); + cbs_cmd_build_file_paths(&cmd, obj_files); + cbs_cmd_build(&cmd, LDFLAGS); + cbs_cmd_run(&cmd); + + cbs_run(bin_file); return 0; } diff --git a/include/parser.h b/include/parser.h new file mode 100644 index 0000000..ddcca8b --- /dev/null +++ b/include/parser.h @@ -0,0 +1,17 @@ +#ifndef _PARSER_H_ +#define _PARSER_H_ + +#include +#include + +#include "raylib.h" + +extern FILE *file; +extern char *line_buffer; +extern char *keys; +extern unsigned int *color_table; +extern unsigned int *pixels; + +bool parse_xpm_file(Image *image, const char *file_path); + +#endif // _PARSER_H_ diff --git a/include/tokenizer.h b/include/tokenizer.h new file mode 100644 index 0000000..5e0893a --- /dev/null +++ b/include/tokenizer.h @@ -0,0 +1,13 @@ +#ifndef _TOKENIZER_H_ +#define _TOKENIZER_H_ + +#include +#include + +int get_next_line(char **buffer, FILE *file); +void check_next_token(char **string, char *token); +char *get_next_token(char **string); +bool get_terminal_token(char **string, char **token); +size_t convert_token_to_num(char *token, int base); + +#endif // _TOKENIZER_H_ diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..ce0a356 --- /dev/null +++ b/include/utils.h @@ -0,0 +1,43 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#include +#include +#include + +#include "parser.h" + +#define SIMPLE_XPM_MALLOC(p, size) \ + do { \ + p = malloc(size); \ + if (p == NULL) { \ + fprintf(stderr, "simplexpm: OUT OF MEMORY (buy more RAM?)"); \ + exit(EXIT_FAILURE); \ + } \ + memset(p, 0, size); \ + } while (0) + +#define SIMPLE_XPM_FREE(p) \ + do { \ + if (p) free(p); \ + p = NULL; \ + } while (0) + +#define ERROR_MESSAGE_CAP 2048 +extern char error_message[ERROR_MESSAGE_CAP]; +extern jmp_buf env; + +#define SIMPLE_XPM_ERROR(...) \ + do { \ + if (file) fclose(file); \ + SIMPLE_XPM_FREE(line_buffer); \ + SIMPLE_XPM_FREE(keys); \ + SIMPLE_XPM_FREE(color_table); \ + SIMPLE_XPM_FREE(pixels); \ + snprintf(error_message, ERROR_MESSAGE_CAP, __VA_ARGS__); \ + siglongjmp(env, 1); \ + } while (0) + +char *strstrip(char **string); + +#endif // _UTILS_H_ diff --git a/include/xpm_mode.h b/include/xpm_mode.h new file mode 100644 index 0000000..3dc0e98 --- /dev/null +++ b/include/xpm_mode.h @@ -0,0 +1,15 @@ +#ifndef _XPM_MODE_H_ +#define _XPM_MODE_H_ + +typedef enum { + XPM_MODE_MONO = 0, + XPM_MODE_SYMBOLIC, + XPM_MODE_GRAYSCALE_4, + XPM_MODE_GRAYSCALE, + XPM_MODE_COLOR, + NUM_XPM_MODES, +} Xpm_Mode; + +Xpm_Mode convert_token_to_mode(char *token); + +#endif // _XPM_MODE_H_ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..90195e5 --- /dev/null +++ b/src/main.c @@ -0,0 +1,63 @@ +#include +#include +#include + +#include "parser.h" +#include "raylib.h" +#include "stb_c_lexer.h" +#include "utils.h" + +#define FILE_PATH_CAP 2048 + +int main(int argc, char **argv) { + char file_path[FILE_PATH_CAP] = {0}; + Texture2D texture = {0}; + bool have_texture = false; + + // Check if a file was given on the command line + if (argc >= 2) { + strncpy(file_path, argv[2], FILE_PATH_CAP); + Image image = {0}; + if (!parse_xpm_file(&image, file_path)) + have_texture = false; + else { + UnloadTexture(texture); + texture = LoadTextureFromImage(image); + have_texture = true; + } + } + + int screenWidth = 800; + int screenHeight = 600; + SetTraceLogLevel(LOG_WARNING); + InitWindow(screenWidth, screenHeight, "simplexpm"); + + while (!WindowShouldClose()) { + if (IsFileDropped()) { + FilePathList file_paths = LoadDroppedFiles(); + strncpy(file_path, file_paths.paths[0], FILE_PATH_CAP); + UnloadDroppedFiles(file_paths); + Image image = {0}; + if (!parse_xpm_file(&image, file_path)) + have_texture = false; + else { + UnloadTexture(texture); + texture = LoadTextureFromImage(image); + have_texture = true; + } + } + + BeginDrawing(); + ClearBackground(RAYWHITE); + if (have_texture) + DrawTexture(texture, screenWidth / 2 - texture.width / 2, screenHeight / 2 - texture.height / 2, WHITE); + else + DrawText(error_message, GetScreenWidth() / 2, GetScreenHeight() / 2, 24, RED); + EndDrawing(); + } + + UnloadTexture(texture); + CloseWindow(); + + return 0; +} diff --git a/src/main.o b/src/main.o new file mode 100644 index 0000000000000000000000000000000000000000..ddc851e3a1644ecd73d1c16403746e025313520d GIT binary patch literal 2816 zcmbVOTWDNG7@n=YY}>TEYO7Tg_90*@9!#TBs|1oZsT0{qv?-0COqbo$&C`S!{6L8OO4x`7sa zl~Og6t&6epc%hsVBHb6*2+#U?rF`Wa_-M{L;@-TWc@w1&_NX}GWJ_)~8!wKMAKza{(=`8b1=a?vjz_RcneNJtZH4ykH_- zch0lv1}UeuL2E26ISZM+VVKq=POd}3+-({rEe)@(CNB^lS2J8q`+N=Z=tpXhw4GdMU&fkpY{P zC!tAU&&|pcXpLayKc-D&de=>|>IPZ3yZr|kjoy47U8OP6!CV{*4A(UeVuFJKEK#(Q z69!HnBhb==&ReEjH;tce7zZWeaQBIBEQUO6xTd+9$6_!Dp~YCa8bs(OwXq81VMzY} zDsbx2^*a8yRWQESS7FHH>aW5Ggj-j^vIz4n`KT!NR9zhcyC=?p2TxwECs+LEG4n?cDX@>n5-OU<3rE%`Y0(~^5U zc*27x3AC}Lz0EqP<7sTxL2TAEZPs2rkyNj>C)G9extcKxWZ2* zxW?@=xWf0$B_v&CIM~NOrOW5VPmEh)bFEOS7VU{@iITig{Cl6Sxtj`IFjQi%JjY@a z$yl;&L;MuH+M&A-HT4I^ffBqMtaoejtu_0$1kZ-XQM;Wn>nQLJ#=3JroJC6j6Tsa- z_*z{+{H$dd(P#HBKs;gAcfdICOCUyQJq*NNu;M_ZVa-Fptz&%vB)%dL_q6pqa69k; z;8x%k;GMwl5rm1cE&=fpSQmgv;CUdX$@&OLq3;24Sz7}@;=dnA{FgCi;{OUr{Io}j zH|NVw`v^`mUI68}J_}5s5tI+n2#Ks4LRhAUA}rq!9()Mys`3BgpezX5!eBxe8s literal 0 HcmV?d00001 diff --git a/src/simplexpm.c b/src/parser.c similarity index 57% rename from src/simplexpm.c rename to src/parser.c index 85babb1..ecabf1e 100644 --- a/src/simplexpm.c +++ b/src/parser.c @@ -1,17 +1,13 @@ #include -#include #include #include #include -#include #include -#include #include "raylib.h" - -#include "../external/stb/stb_c_lexer.h" - -#define FILE_PATH_CAP 2048 +#include "tokenizer.h" +#include "utils.h" +#include "xpm_mode.h" FILE *file; char *line_buffer; @@ -19,136 +15,6 @@ char *keys; unsigned int *color_table; unsigned int *pixels; -#define SIMPLE_XPM_MALLOC(p, size) \ - do { \ - p = malloc(size); \ - if (p == NULL) { \ - fprintf(stderr, "simplexpm: OUT OF MEMORY (buy more RAM?)"); \ - exit(EXIT_FAILURE); \ - } \ - memset(p, 0, size); \ - } while (0) - -#define SIMPLE_XPM_FREE(p) \ - do { \ - if (p) free(p); \ - p = NULL; \ - } while (0) - -#define ERROR_MESSAGE_CAP 2048 -char error_message[ERROR_MESSAGE_CAP] = "Drag and drop .xpm files here"; -jmp_buf env; - -#define SIMPLE_XPM_ERROR(...) \ - do { \ - if (file) fclose(file); \ - SIMPLE_XPM_FREE(line_buffer); \ - SIMPLE_XPM_FREE(keys); \ - SIMPLE_XPM_FREE(color_table); \ - SIMPLE_XPM_FREE(pixels); \ - snprintf(error_message, ERROR_MESSAGE_CAP, __VA_ARGS__); \ - siglongjmp(env, 1); \ - } while(0) - -typedef enum { - XPM_MODE_MONO = 0, - XPM_MODE_SYMBOLIC, - XPM_MODE_GRAYSCALE_4, - XPM_MODE_GRAYSCALE, - XPM_MODE_COLOR, - NUM_XPM_MODES, -} Xpm_Mode; - -Xpm_Mode convert_token_to_mode(char *token) { - if (strcmp(token, "m") == 0) return XPM_MODE_MONO; - if (strcmp(token, "s") == 0) return XPM_MODE_SYMBOLIC; - if (strcmp(token, "g4") == 0) return XPM_MODE_GRAYSCALE_4; - if (strcmp(token, "g") == 0) return XPM_MODE_GRAYSCALE; - if (strcmp(token, "c") == 0) return XPM_MODE_COLOR; - SIMPLE_XPM_ERROR("\"%s\" is not a valid color mode", token); -} - -char *strstrip(char **string) { - for (; isspace(**string) && **string != '\0'; ++*string); - if (**string == '\0') return *string; - char *end; - for (end = *string + strlen(*string); isspace(*(end - 1)); --end); - *end = '\0'; - return *string; -} - -// TODO: Ignore comments -int get_next_line(char **buffer, FILE *file) { - static size_t line_cap = 0; - errno = 0; - if (getline(buffer, &line_cap, file) == -1) { - if (errno != 0) - SIMPLE_XPM_ERROR("Unable to parse provided file: expected a new line"); - return 0; - } - return 1; -} - -void check_next_token(char **string, char *token) { - size_t token_len = strlen(token); - if (strncmp(strstrip(string), token, token_len) != 0) - SIMPLE_XPM_ERROR("Unable to parse provided file: expected token \"%s\"", token); - *string += token_len; -} - -char *get_next_token(char **string) { - char *result; - 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"); - if (strlen(result) != strlen(strstrip(&result))) - SIMPLE_XPM_ERROR("Weird whitespace characters between array tokens"); - return result; -} - -bool get_terminal_token(char **string, char **token) { - bool result = true; - while (**string == '\t' || **string == ' ') ++*string; - *token = *string; - while (**string != '\t' && **string != ' ') { - if (**string == '"') { - *(*string)++ = '\0'; - goto check_comma; - } - ++*string; - } - *(*string)++ = '\0'; - if (*token == *string) - SIMPLE_XPM_ERROR("Couldn't parse potential last token"); - while (**string == '\t' || **string == ' ') ++*string; - if (**string != '"') { - result = false; - goto defer; - } - -check_comma: - check_next_token(string, ","); - -defer: - if (strlen(*token) != strlen(strstrip(token))) - SIMPLE_XPM_ERROR("Weird whitespace characters between array tokens"); - return result; -} - -size_t convert_token_to_num(char *token, int base) { - if (token == NULL) - SIMPLE_XPM_ERROR("Expected non-null token to parse"); - 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); - return (size_t)result; -} - bool parse_xpm_file(Image *image, const char *file_path) { switch (sigsetjmp(env, 0)) { case 1: @@ -329,57 +195,3 @@ bool parse_xpm_file(Image *image, const char *file_path) { }; return true; } - -int main(int argc, char **argv) { - char file_path[FILE_PATH_CAP] = {0}; - Texture2D texture = {0}; - bool have_texture = false; - - // Check if a file was given on the command line - if (argc >= 2) { - strncpy(file_path, argv[2], FILE_PATH_CAP); - Image image = {0}; - if (!parse_xpm_file(&image, file_path)) - have_texture = false; - else { - UnloadTexture(texture); - texture = LoadTextureFromImage(image); - have_texture = true; - } - } - - int screenWidth = 800; - int screenHeight = 600; - SetTraceLogLevel(LOG_WARNING); - InitWindow(screenWidth, screenHeight, "simplexpm"); - - while (!WindowShouldClose()) { - if (IsFileDropped()) { - FilePathList file_paths = LoadDroppedFiles(); - strncpy(file_path, file_paths.paths[0], FILE_PATH_CAP); - UnloadDroppedFiles(file_paths); - Image image = {0}; - if (!parse_xpm_file(&image, file_path)) - have_texture = false; - else { - UnloadTexture(texture); - texture = LoadTextureFromImage(image); - have_texture = true; - } - } - - BeginDrawing(); - ClearBackground(RAYWHITE); - if (have_texture) { - DrawTexture(texture, screenWidth / 2 - texture.width / 2, screenHeight / 2 - texture.height / 2, WHITE); - } else { - DrawText(error_message, GetScreenWidth() / 2, GetScreenHeight() / 2, 24, RED); - } - EndDrawing(); - } - - UnloadTexture(texture); - CloseWindow(); - - return 0; -} diff --git a/src/parser.o b/src/parser.o new file mode 100644 index 0000000000000000000000000000000000000000..283a23bcc9fdcd79187ba9a76efd68030ebc92d6 GIT binary patch literal 15816 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 Pt6gun*zNNLO11w6h=PUU literal 0 HcmV?d00001 diff --git a/src/tokenizer.c b/src/tokenizer.c new file mode 100644 index 0000000..c9528f7 --- /dev/null +++ b/src/tokenizer.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include + +#include "raylib.h" +#include "utils.h" + +// TODO: Ignore comments +int get_next_line(char **buffer, FILE *file) { + static size_t line_cap = 0; + errno = 0; + if (getline(buffer, &line_cap, file) == -1) { + if (errno != 0) + SIMPLE_XPM_ERROR("Unable to parse provided file: expected a new line"); + return 0; + } + return 1; +} + +void check_next_token(char **string, char *token) { + size_t token_len = strlen(token); + if (strncmp(strstrip(string), token, token_len) != 0) + SIMPLE_XPM_ERROR("Unable to parse provided file: expected token \"%s\"", token); + *string += token_len; +} + +char *get_next_token(char **string) { + char *result; + 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"); + if (strlen(result) != strlen(strstrip(&result))) + SIMPLE_XPM_ERROR("Weird whitespace characters between array tokens"); + return result; +} + +bool get_terminal_token(char **string, char **token) { + bool result = true; + while (**string == '\t' || **string == ' ') ++*string; + *token = *string; + while (**string != '\t' && **string != ' ') { + if (**string == '"') { + *(*string)++ = '\0'; + goto check_comma; + } + ++*string; + } + *(*string)++ = '\0'; + if (*token == *string) + SIMPLE_XPM_ERROR("Couldn't parse potential last token"); + while (**string == '\t' || **string == ' ') ++*string; + if (**string != '"') { + result = false; + goto defer; + } + +check_comma: + check_next_token(string, ","); + +defer: + if (strlen(*token) != strlen(strstrip(token))) + SIMPLE_XPM_ERROR("Weird whitespace characters between array tokens"); + return result; +} + +size_t convert_token_to_num(char *token, int base) { + if (token == NULL) + SIMPLE_XPM_ERROR("Expected non-null token to parse"); + 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); + return (size_t)result; +} diff --git a/src/tokenizer.o b/src/tokenizer.o new file mode 100644 index 0000000000000000000000000000000000000000..4526e7472f04b2534c11030e1fb4649850bd04be GIT binary patch literal 7728 zcmeI1e{d9M8OPrPN-s*ev=u4SQdar{r*cdYaZ>6Hp>TEECK@fVpwi{IY?33Fy?A#a zp<{+H7i=y!QM6Pu%%yjN(kG|aW5v5KsYno~$++-LV zQYlve4P(`c)hos_TtEC{S&A{b$s3YkL{sTx%&L(BhHKh`_w9#la#jGmBC|gxf;zlcWq;ARVx&xK%H zm33azah+0&d)xQ@O8L=P_L!cn9L(-7%asqdmk*R>U+xGGNUL^@JshiS__&>SDEuC+ z4D;Eq^GU6D`hKC^Jr3Gp*R1#+&%N#Cd+mPSJ3&AHLh`~`5)M?X>kG_lXrYK- z-@1=)6g}%7-Z?4{3f_WT6|=s@z4n5ZD+=tnK69?9J$!m1^H0M3>5lN}g86X4yyMyY zz_wcoS$;ixMBlpKX|(typBjD#_m0Eky=g6Yb4d*p#+pqh^ZLDr>FQj=T$_b`ooCIQ z^cKTiGYfOZo=g1`4L0Xee@D2#FxXd|OZMcP?`-xkXVvg5%mr!DehY5FoE)3-g^k|T z)upheI$L0OukCJD-p1+3Gvbq8T{^;NZubRV=yg{ZoOEP;Ddqko+jtgR^sD<3%v8QF z2XMyn^z@|Pm-ftdhpr``t30cB%Haub&q1tZL$XuZ#*@2UJX3<_h37X6!k`Ltez5oF zSe4u<--K6%XCMyqg<5&Iz5GyF7W;Ge^frED*z2w?gP886>-s9K$cDJ7r4w31B$+a` zhGb$>tjes?s$+3;nPxUOn9(%Eh-R5hT0CZ%YO+<*i8|BL=HHQ;uZlFaGSL{XvKFMJ zoq}NtA6C#jimFwyD$PoyrBO8KYUthu6F#KPWPQwv#HGR`W-M8yHPyz_W(r>`Of6a) zN#d)8nM|R4y2(WQkz_Km*(sm$I?<3wn^rmod+|uh^!Yu`eoLbFr^@#xjoU&V8?+Z{wcL$X7M+sth|oj zOPE-06|Sz4E0>F-T=CmZIf-XNdpl6>e3l5V6Hd64x- zL>>_S2E?bW&_NJ?!QCQ1BkTq-RKYF~$L-ML!Ws~L9sC?P8!Qod3COta1R2*nka3+y zWyWDRh?h`%>GOnjZ{{xXbg^z)ZD<%3mk-sebEXcS@MPDNF0^!Xd zcp#Tn#eLa?#%>@?znwAmf=W`hdt6P>K0( zf{gQZkoNx~@=@Vlka4~UGR_|h>)C{rsuupAz{y!Yv^EZx(%n$cFG?kp4de(*I?`kAWPgIUvVr zhR9Pv#`P|Ck&NpM2$zFLLB@3eWLz(R^nWKvzkek16T()Iacvg8CGtAqgCOHtDf)Xw zzDqb8WL(9f_lx{btmn*s6J%VkfsE@_;Zq>}|1L=XzXj6&I*|TXf%N}NApQS5NdH%f zyhNyh^nZ@%XNvr97-9Y?kp900vi_e%J|cV(q@T}~M$P;`R zCj1B9b@q6G)DMXKityJU1!gFqLY}Oz(sv4I**C_mT|?^L63aiBeU%I@_q>8v z_U3wI%$1AucX{NPNB*=&e!wFy_sF|FvNB9-lQQbe%_(Ix#G1`Gh=0B%lZm7*}@yq zS~FVb)Q}unaQE$oTPk5~GLy*Xz8}8^cF(pO=|r3kr>qA2H#1!gb9Kt7j>Z!y({9T? nfQ&Wjh&-w&{Kqn$NE&G#XV49d*r+#CsYngP>ZEC+tJHr0|1_RU literal 0 HcmV?d00001 diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..9588307 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,18 @@ +#include +#include +#include +#include + +#include "utils.h" + +char error_message[ERROR_MESSAGE_CAP] = "Drag and drop .xpm files here"; +jmp_buf env; + +char *strstrip(char **string) { + for (; isspace(**string) && **string != '\0'; ++*string); + if (**string == '\0') return *string; + char *end; + for (end = *string + strlen(*string); isspace(*(end - 1)); --end); + *end = '\0'; + return *string; +} diff --git a/src/utils.o b/src/utils.o new file mode 100644 index 0000000000000000000000000000000000000000..c6608d2a748fcd77e11d6cd6c8bce1fba4a3ffdb GIT binary patch literal 3112 zcmeHJ&1(};5Pw_Sbp70bf{GsYAec)fda^fz3A}>=krcehb8TLmK(h(E(FQ?K(n?}3 z9`q=95&92!EmlSFBzWpSAlZO|rxHE5{$}^RWP1>LmK`!X^PBHCxy+Z}KmN=!W*lPp zfM>zx3_dm(bQatr$3N)q;nNv-(9b}RUvK^Cr(n- zJ8fmmskvT5s`aQ1!~sIcnpp9ihSYffdu>(knySb3I~4}3DK!#T@I3>LdRa$U224av z$-aezImj_&9uk7x1Sg4NiKBfc9S6{tc>f#ke$Vs%qn~_G0yAs-YCxHnKX=EhR~}j$ zCxIqTv-^u#FW>i;hR;gFEyLQR@kZz916FY+f3ibQ;(c@UCJe*<*_+u(ARG zRGoa&$DLBD@$eQiI$0xoY~Fm1s0*;42fy2+qazIUeai|bvQKBOAJ3?~w~)BY7G6Q( zPF*;yFu74CLl=xi$D8U*c~)WyQo*w?Ac-!56K+PAR1z~G-3LtgZ4bYCE7I1a3$y1n SJ<*W9@2pBD>b{SwShByn^Rkiv literal 0 HcmV?d00001 diff --git a/src/xpm_mode.c b/src/xpm_mode.c new file mode 100644 index 0000000..812be3b --- /dev/null +++ b/src/xpm_mode.c @@ -0,0 +1,13 @@ +#include + +#include "xpm_mode.h" +#include "utils.h" + +Xpm_Mode convert_token_to_mode(char *token) { + if (strcmp(token, "m") == 0) return XPM_MODE_MONO; + if (strcmp(token, "s") == 0) return XPM_MODE_SYMBOLIC; + if (strcmp(token, "g4") == 0) return XPM_MODE_GRAYSCALE_4; + if (strcmp(token, "g") == 0) return XPM_MODE_GRAYSCALE; + if (strcmp(token, "c") == 0) return XPM_MODE_COLOR; + SIMPLE_XPM_ERROR("\"%s\" is not a valid color mode", token); +} diff --git a/src/xpm_mode.o b/src/xpm_mode.o new file mode 100644 index 0000000000000000000000000000000000000000..33dd38934d6eb18df5a6ad0094f1f039a9cc59c4 GIT binary patch literal 1852 zcmb_dOKTHR6ux~|+nQ1p6kLqOf(ThCR=bI`XdsIeL|f>l+@{k>GB%kBGt*iXp%@<- zW5s`kaNHD-Se1}d(R}#zkU4C zB1Bz-zyfWAw$@`&ppfm*0y+L7Hz*deo6+Z}DM+aviIk2upzR-A(SD&`I^yN}|<;pM{MQrvxUIl9D8_A>6{+=Lr_>+KbztFioJWpp7cY?0b8 zQbHBoJ$ARE+lpa2N2|(=2scd01+Q?*sn7mVT=NCZjnRmKft_)u?x5X{x@Xs5DZ^>VFai+Uc<>3 z^pDl>Xbm5%;bsk|`w7;gdk%8+T*Y_R@Nf+mQZuH7oYYR)Lgw@tEd$Kxh9<|Sl1a@H z($-TM(@34j=3qOPN+_jmp|mELIo0xo9`1^@s6 literal 0 HcmV?d00001 -- 2.51.0