enowars5-service-stldoctor

STL-Analyzing A/D Service for ENOWARS5 in 2021
git clone https://git.sinitax.com/sinitax/enowars5-service-stldoctor
Log | Files | Refs | README | LICENSE | sfeed.txt

commit 14bc8a3883663656cd4254567a978002c062992d
parent 5569ec2abd2c8f31554a02587fda842e4da7eba3
Author: Louis Burda <quent.burda@gmail.com>
Date:   Thu, 24 Jun 2021 21:23:02 +0200

refactored code for readability and keeping within 80ch limit, updated service source

Diffstat:
Mdo.sh | 2+-
Mservice/src/main.c | 114++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mservice/src/stlfile.c | 131+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Mservice/src/stlfile.h | 2++
Mservice/src/util.h | 5++++-
Msrc/main.c | 114++++++++++++++++++++++++++++++++++++++-----------------------------------------
Msrc/stlfile.c | 131+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/stlfile.h | 2++
Msrc/util.h | 5++++-
9 files changed, 293 insertions(+), 213 deletions(-)

diff --git a/do.sh b/do.sh @@ -43,7 +43,7 @@ elif [ "$1" == "cleansrc" ]; then if [ ! -z $(echo "$path" | grep '.[hc]$') ]; then sed -i -e 's/^\s*\/\*.*\*\/\s*$//g' "$path" # remove /* */ style comments sed -i -e 's/\s*\/\*.*\*\/\s*/ /g' "$path" # remove /* */ style comments - sed -i -e 's/\/\/.*//g' "$path" # remove // style comments + sed -i -e 's/\s*\/\/.*//g' "$path" # remove // style comments sed -i -e ':a;N;$!ba;s/\n\{3,\}/\n\n/g' "$path" # collapse multiple newlines sed -i -e 's/fprintf(\s*stderr\s*,\s*/printf(/g' "$path" # replace fprintf stderr elif [ "$(basename "$path")" == "Makefile" ]; then diff --git a/service/src/main.c b/service/src/main.c @@ -50,9 +50,10 @@ int echo = 0, loggedin = 0; int save_submission(struct parseinfo *info, char *stldata, int stlsize) { - DIR *d; - FILE *f = NULL; char *dirpath = NULL, *infopath = NULL, *modelpath = NULL; + FILE *f = NULL; + int status = 0; + DIR *d; if (loggedin) dirpath = aprintf("%s/.%s-%i", resultdir, info->hash, time(NULL)); @@ -63,33 +64,29 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize) modelpath = aprintf("%s/%s", dirpath, "model"); if (!(f = fopen(modelpath, "w+"))) goto fail; if (fwrite(stldata, 1, stlsize, f) != stlsize) goto fail; - fclose(f); - f = NULL; + NFCLOSE(f); infopath = aprintf("%s/%s", dirpath, "info"); if (!(f = fopen(infopath, "w+"))) goto fail; if (save_info(info, f) != OK) goto fail; - fclose(f); - f = NULL; + NFCLOSE(f); + +exit: + if (f) fclose(f); free(dirpath); free(modelpath); free(infopath); - return OK; + return status; fail: - if (f) fclose(f); - if (infopath) remove(infopath); if (modelpath) remove(modelpath); if (dirpath) remove(dirpath); - free(dirpath); - free(modelpath); - free(infopath); - - return FAIL; + status = 1; + goto exit; } int @@ -104,50 +101,51 @@ handle_download(const char *scandir) { char *infopath, *modelpath; size_t i, size; + int status = 0; FILE *f; infopath = aprintf("%s/%s", scandir, "info"); if (!(f = fopen(infopath, "r"))) { - printf("ERR: Selected result is missing!\n"); - goto cleanup; + ERR("Selected result is missing!\n"); + goto fail; } free_info(&cached); if (load_info(&cached, f) != OK) { - printf("ERR: Failed to parse info file!\n"); - goto cleanup; + ERR("Failed to parse info file!\n"); + goto fail; } - fclose(f); - f = NULL; + NFCLOSE(f); print_info(&cached); if (strchr(ask("Download the model? "), 'y')) { modelpath = aprintf("%s/%s", scandir, "model"); if (!(f = fopen(modelpath, "r"))) { - printf("ERR: Failed to access file!\n"); - goto cleanup; + ERR("Failed to access file!\n"); + goto fail; } fseek(f, 0, SEEK_END); size = ftell(f); fseek(f, 0, SEEK_SET); if (size > MAXFILESIZE) { - printf("ERR: File is too large!\n"); - goto cleanup; + ERR("File is too large!\n"); + goto fail; } printf("Here you go.. (%liB)\n", size); while ((i = getc(f)) != EOF) putc(i, stdout); - fclose(f); - f = NULL; + NFCLOSE(f); } - return 0; - -cleanup: +exit: if (f) fclose(f); free(infopath); free(modelpath); - return 1; + return status; + +fail: + status = 1; + goto exit; } void @@ -201,21 +199,21 @@ upload_cmd(const char *arg) resp = ask("How large is your file? "); len = strtoul(resp, &end, 10); if (len <= 0 || len >= MAXFILESIZE || *end) { - printf("ERR: Invalid file length!\n"); + ERR("Invalid file length!\n"); return; } printf("Ok! Im listening..\n"); contents = checkp(malloc(len + 1)); if (fread(contents, 1, len, stdin) != len) { - printf("ERR: Not enough data received!\n"); + ERR("Not enough data received!\n"); goto cleanup; } contents[len] = '\0'; if ((cached.valid = parse_file(&cached, contents, len))) { if (save_submission(&cached, contents, len) != OK) - printf("ERR: Failed to save your submission!\n"); + ERR("Failed to save your submission!\n"); else printf("Your file was saved with ID %s!\n", cached.hash); } @@ -235,7 +233,7 @@ search_cmd(const char *arg) if (arg && !strcmp(arg, "last")) { if (!cached.valid) { - printf("ERR: No cached info report available\n"); + ERR("No cached info report available\n"); return; } hash = cached.hash; @@ -244,7 +242,7 @@ search_cmd(const char *arg) } if (!(d = opendir(resultdir))) { - printf("ERR: Unable to access upload directory!\n"); + ERR("Unable to access upload directory!\n"); return; } @@ -256,14 +254,15 @@ search_cmd(const char *arg) paths[pathc++] = checkp(strdup(de->d_name)); if (pathc == pathcap) { pathcap *= 2; - paths = checkp(realloc(paths, pathcap * sizeof(char*))); + paths = realloc(paths, pathcap * sizeof(char*)); + checkp(paths); } } } closedir(d); if (pathc == 0) { - printf("ERR: Couldn't find a matching scan result!\n"); + ERR("Couldn't find a matching scan result!\n"); goto cleanup; } @@ -272,16 +271,13 @@ search_cmd(const char *arg) if (strchr(resp, 'q')) break; which = strtoul(resp, &end, 10); if (which >= pathc || which < 0 || *end) { - printf("ERR: Invalid index!\n"); + ERR("Invalid index!\n"); goto cleanup; } scandir = aprintf("%s/%s", resultdir, paths[which]); - if (handle_download(scandir)) goto cleanup; - - free(scandir); - scandir = NULL; + NFREE(scandir); } cleanup: @@ -301,7 +297,7 @@ list_cmd(const char *arg) DIR *d; if (!loggedin) { - printf("ERR: Not logged in!\n"); + ERR("Not logged in!\n"); return; } @@ -311,13 +307,12 @@ list_cmd(const char *arg) if (*de->d_name == '.' && !strchr(".", de->d_name[1])) { printf(">> %s\n", de->d_name); path = aprintf("%s/%s/info", resultdir, de->d_name); - if ((f = fopen(path, "r"))) { - if (load_info(&info, f) == OK) - print_info(&info); - else - printf("ERR: Failed to read saved file info!\n"); - fclose(f); + if ((f = fopen(path, "r")) && load_info(&info, f) == OK) { + print_info(&info); + } else { + ERR("Failed to read saved file info!\n"); } + if (f) fclose(f); free(path); } } @@ -331,7 +326,7 @@ auth_cmd(const char *arg) int ret; if (loggedin) { - printf("ERR: Already logged in!\n"); + ERR("Already logged in!\n"); return; } @@ -343,7 +338,7 @@ auth_cmd(const char *arg) } else if (ret && errno == EEXIST) { printf("Success!\nWelcome back!\n"); } else { - printf("ERR: Auth failed!\n"); + ERR("Auth failed!\n"); return; } @@ -364,14 +359,13 @@ cleanexit() int main() { + struct command *c; const char *cmd, *envstr; char *cp, *arg; int exit, i, cmdlen; - if (!(envstr = getenv("RESULTDIR"))) { - printf("ERR: RESULTDIR not defined\n"); - return 1; - } + if (!(envstr = getenv("RESULTDIR"))) + die("RESULTDIR not defined\n"); resultdir = checkp(strdup(envstr)); @@ -395,14 +389,16 @@ main() cmdlen = cp ? cp - cmd : strlen(cmd); for (i = 0; i < ARRSIZE(commands); i++) { - if (!strncmp(commands[i].name, cmd, cmdlen) - && cmdlen == strlen(commands[i].name)) { - commands[i].func(arg); + c = &commands[i]; + if (!strncmp(c->name, cmd, cmdlen) && !c->name[cmdlen]) { + c->func(arg); break; } } if (i == ARRSIZE(commands) && strlen(cmd) != 0) - printf("No such command!\n"); + ERR("No such command!\n"); } + + return EXIT_SUCCESS; } diff --git a/service/src/stlfile.c b/service/src/stlfile.c @@ -27,7 +27,8 @@ stack_push(struct stack *stack, int v) { if (stack->count == stack->cap) { stack->cap *= 2; - stack->data = checkp(realloc(stack->data, sizeof(int) * stack->cap)); + stack->data = realloc(stack->data, sizeof(int) * stack->cap); + checkp(stack->data); } stack->data[stack->count] = v; @@ -98,7 +99,6 @@ consume_keyword(char **start) for (i = 0; i < ARRSIZE(kwmap); i++) { len = strlen(kwmap[i].str); if (!strncmp(kwmap[i].str, bp, len) && (!bp[len] || isws(bp[len]))) { - *start = bp + len + (bp[len] ? 1 : 0); return kwmap[i].code; } @@ -107,9 +107,6 @@ consume_keyword(char **start) return KW_UNKNOWN; } -#define PARSE_FAIL(...) \ - do { printf("FORMAT ERR: " __VA_ARGS__); goto fail; } while (0) - int parse_file_ascii(struct parseinfo *info, char *buf, size_t len) { @@ -135,81 +132,113 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) switch (kw) { case KW_SOLID_BEGIN: stack_push(&states, STATE_SOLID); - if (stack_ind(&states, KW_SOLID_BEGIN) != -1) - PARSE_FAIL("Multiple nested solids!\n"); + if (stack_ind(&states, KW_SOLID_BEGIN) != -1) { + FMT_ERR("Multiple nested solids!\n"); + goto format_error; + } tmp = bp; - if (!consume_keyword(&bp) && (arg = consume_arg(&bp, &end))) { + if (!consume_keyword(&bp) + && (arg = consume_arg(&bp, &end))) { info->solidname = strndup(arg, end - arg); } else { bp = tmp; } break; case KW_SOLID_END: - if ((kw = stack_pop(&states)) != STATE_SOLID) - PARSE_FAIL("Improper nesting, parent: %s\n", kwmap[kw].str); + if ((kw = stack_pop(&states)) != STATE_SOLID) { + FMT_ERR("Improper nesting, parent: %s\n", + kwmap[kw].str); + goto format_error; + } tmp = bp; if (info->solidname && !consume_keyword(&bp) && (arg = consume_arg(&bp, &end))) { - if (strncmp(info->solidname, arg, end - arg)) - PARSE_FAIL("Solid end/begin names do not match!\n"); + if (strncmp(info->solidname, arg, end - arg)) { + FMT_ERR("Solid names do not match!\n"); + goto format_error; + } } else { bp = tmp; } break; case KW_LOOP_BEGIN: stack_push(&states, STATE_LOOP); - if (stack_ind(&states, KW_LOOP_BEGIN) != -1) - PARSE_FAIL("Multiple nested loops!\n"); + if (stack_ind(&states, KW_LOOP_BEGIN) != -1) { + FMT_ERR("Multiple nested loops!\n"); + goto format_error; + } break; case KW_LOOP_END: - if ((kw = stack_pop(&states)) != STATE_LOOP) - PARSE_FAIL("Improper nesting, parent: %s\n", kwmap[kw].str); + if ((kw = stack_pop(&states)) != STATE_LOOP) { + FMT_ERR("Improper nesting, parent: %s\n", + kwmap[kw].str); + goto format_error; + } info->loopcount++; break; case KW_FACET_BEGIN: stack_push(&states, STATE_FACET); - if (stack_ind(&states, KW_LOOP_BEGIN) != -1) - PARSE_FAIL("Multiple nested facets!\n"); + if (stack_ind(&states, KW_LOOP_BEGIN) != -1) { + FMT_ERR("Multiple nested facets!\n"); + goto format_error; + } for (i = 0; i < 3; i++) { - if (!(arg = consume_arg(&bp, &end))) - PARSE_FAIL("Facet with less than 3 args!\n"); + if (!(arg = consume_arg(&bp, &end))) { + FMT_ERR("Facet with < 3 args!\n"); + goto format_error; + } farg = strtof(arg, &tmp); - if (!isws(*tmp)) - PARSE_FAIL("Facet with invalid arg '%s'!\n", arg); + if (!isws(*tmp)) { + FMT_ERR("Facet arg '%s'\n", arg); + goto format_error; + } } break; case KW_FACET_END: - if ((kw = stack_pop(&states)) != STATE_FACET) - PARSE_FAIL("Improper nesting, parent: %s\n", kwmap[kw].str); + if ((kw = stack_pop(&states)) != STATE_FACET) { + FMT_ERR("Improper nesting, parent: %s\n", + kwmap[kw].str); + goto format_error; + } break; case KW_VERTEX: for (i = 0; i < 3; i++) { - if (!(arg = consume_arg(&bp, &end))) - PARSE_FAIL("Vertex with less than 3 args!\n"); + if (!(arg = consume_arg(&bp, &end))) { + FMT_ERR("Vertex with < 3 args\n"); + goto format_error; + } farg = strtof(arg, &tmp); - if (!isws(*tmp)) - PARSE_FAIL("Vertex with invalid arg '%s'!\n", arg); + if (!isws(*tmp)) { + FMT_ERR("Vertex arg '%s'\n", arg); + goto format_error; + } info->bbmin[i] = MIN(info->bbmin[i], farg); info->bbmax[i] = MAX(info->bbmax[i], farg); } break; case KW_UNKNOWN: prev = skipws(prev); - PARSE_FAIL("Expected keyword, got:\n%.*s...\n", 30, prev); + FMT_ERR("Expected keyword, got:\n%.*s...\n", 30, prev); + goto format_error; } prev = bp; } - if (states.count) - PARSE_FAIL("Expected keyword, got:\n%.*s...\n", 30, bp); + if (states.count) { + FMT_ERR("Expected keyword, got:\n%.*s...\n", 30, bp); + goto format_error; + } bp = skipws(bp); - if (*bp) PARSE_FAIL("Extraneous data at end of file\n"); + if (*bp) { + FMT_ERR("Extraneous data at end of file\n"); + goto format_error; + } stack_free(&states); return OK; -fail: +format_error: stack_free(&states); return FAIL; } @@ -223,8 +252,10 @@ parse_file_bin(struct parseinfo *info, char *buf, size_t len) info->type = TYPE_BIN; - if (len < 84) - PARSE_FAIL("Truncated data! (header missing)\n"); + if (len < 84) { + FMT_ERR("Truncated data! (header missing)\n"); + goto fail; + } memcpy(info->header, buf, 80); @@ -248,12 +279,16 @@ parse_file_bin(struct parseinfo *info, char *buf, size_t len) } for (i = 0; i < info->loopcount; i++) { - if (bp + 50 > end) - PARSE_FAIL("Truncated data! (loops missing)\n"); + if (bp + 50 > end) { + FMT_ERR("Truncated data! (loops missing)\n"); + goto fail; + } for (k = 0; k < 12; k++, bp += 4) { v = fle32toh(*(float*)bp); - if (v == INFINITY || v == NAN) - PARSE_FAIL("Encountered invalid float\n"); + if (v == INFINITY || v == NAN) { + FMT_ERR("Encountered invalid float\n"); + goto fail; + } if (k >= 3) { info->bbmin[k % 3] = MIN(info->bbmin[k % 3], v); info->bbmax[k % 3] = MAX(info->bbmax[k % 3], v); @@ -262,11 +297,15 @@ parse_file_bin(struct parseinfo *info, char *buf, size_t len) bp += 2; } - if (bp != end) PARSE_FAIL("Extraneous data at end of file\n"); + if (bp != end) { + FMT_ERR("Extraneous data at end of file\n"); + goto fail; + } return OK; fail: + NFREE(info->solidname); return FAIL; } @@ -277,10 +316,10 @@ parse_file(struct parseinfo *info, char *buf, size_t len) const char *resp; char *bp; - if (info->valid) free_info(info); + free_info(info); if (len < 10) { - printf("ERR: File too small!\n"); + ERR("File too small!\n"); return FAIL; } @@ -297,7 +336,7 @@ parse_file(struct parseinfo *info, char *buf, size_t len) if (!info->modelname) { resp = ask("Please enter your model name: "); if (strlen(resp) < 4) { - printf("ERR: Model name is too short!\n"); + ERR("Model name is too short!\n"); return FAIL; } info->modelname = checkp(strdup(resp)); @@ -403,9 +442,9 @@ print_info(struct parseinfo *info) void free_info(struct parseinfo *info) { - NULLFREE(info->hash); - NULLFREE(info->modelname); - NULLFREE(info->solidname); + NFREE(info->hash); + NFREE(info->modelname); + NFREE(info->solidname); info->valid = 0; } diff --git a/service/src/stlfile.h b/service/src/stlfile.h @@ -9,6 +9,8 @@ #include "util.h" +#define FMT_ERR(...) ERR("FORMAT " __VA_ARGS__) + enum { KW_INVALID = -1, KW_UNKNOWN, diff --git a/service/src/util.h b/service/src/util.h @@ -11,7 +11,10 @@ #define MIN(x,y) ((x) > (y) ? (y) : (x)) #define MAX(x,y) ((x) < (y) ? (y) : (x)) -#define NULLFREE(p) do { free(p); p = NULL; } while (0) +#define ERR(...) printf("ERR: " __VA_ARGS__) + +#define NFREE(p) do { free(p); p = NULL; } while (0) +#define NFCLOSE(f) do { fclose(f); f = NULL; } while (0) #define MHASHLEN 40 diff --git a/src/main.c b/src/main.c @@ -50,9 +50,10 @@ int echo = 0, loggedin = 0; int save_submission(struct parseinfo *info, char *stldata, int stlsize) { - DIR *d; - FILE *f = NULL; char *dirpath = NULL, *infopath = NULL, *modelpath = NULL; + FILE *f = NULL; + int status = 0; + DIR *d; if (loggedin) dirpath = aprintf("%s/.%s-%i", resultdir, info->hash, time(NULL)); @@ -63,33 +64,29 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize) modelpath = aprintf("%s/%s", dirpath, "model"); if (!(f = fopen(modelpath, "w+"))) goto fail; if (fwrite(stldata, 1, stlsize, f) != stlsize) goto fail; - fclose(f); - f = NULL; + NFCLOSE(f); infopath = aprintf("%s/%s", dirpath, "info"); if (!(f = fopen(infopath, "w+"))) goto fail; if (save_info(info, f) != OK) goto fail; - fclose(f); - f = NULL; + NFCLOSE(f); + +exit: + if (f) fclose(f); free(dirpath); free(modelpath); free(infopath); - return OK; + return status; fail: - if (f) fclose(f); - if (infopath) remove(infopath); if (modelpath) remove(modelpath); if (dirpath) remove(dirpath); - free(dirpath); - free(modelpath); - free(infopath); - - return FAIL; + status = 1; + goto exit; } int @@ -104,50 +101,51 @@ handle_download(const char *scandir) { char *infopath, *modelpath; size_t i, size; + int status = 0; FILE *f; infopath = aprintf("%s/%s", scandir, "info"); if (!(f = fopen(infopath, "r"))) { - fprintf(stderr, "ERR: Selected result is missing!\n"); - goto cleanup; + ERR("Selected result is missing!\n"); + goto fail; } free_info(&cached); if (load_info(&cached, f) != OK) { - fprintf(stderr, "ERR: Failed to parse info file!\n"); - goto cleanup; + ERR("Failed to parse info file!\n"); + goto fail; } - fclose(f); - f = NULL; + NFCLOSE(f); print_info(&cached); if (strchr(ask("Download the model? "), 'y')) { modelpath = aprintf("%s/%s", scandir, "model"); if (!(f = fopen(modelpath, "r"))) { - fprintf(stderr, "ERR: Failed to access file!\n"); - goto cleanup; + ERR("Failed to access file!\n"); + goto fail; } fseek(f, 0, SEEK_END); size = ftell(f); fseek(f, 0, SEEK_SET); if (size > MAXFILESIZE) { - fprintf(stderr, "ERR: File is too large!\n"); - goto cleanup; + ERR("File is too large!\n"); + goto fail; } printf("Here you go.. (%liB)\n", size); while ((i = getc(f)) != EOF) putc(i, stdout); - fclose(f); - f = NULL; + NFCLOSE(f); } - return 0; - -cleanup: +exit: if (f) fclose(f); free(infopath); free(modelpath); - return 1; + return status; + +fail: + status = 1; + goto exit; } void @@ -201,21 +199,21 @@ upload_cmd(const char *arg) resp = ask("How large is your file? "); len = strtoul(resp, &end, 10); if (len <= 0 || len >= MAXFILESIZE || *end) { - fprintf(stderr, "ERR: Invalid file length!\n"); + ERR("Invalid file length!\n"); return; } printf("Ok! Im listening..\n"); contents = checkp(malloc(len + 1)); if (fread(contents, 1, len, stdin) != len) { - fprintf(stderr, "ERR: Not enough data received!\n"); + ERR("Not enough data received!\n"); goto cleanup; } contents[len] = '\0'; if ((cached.valid = parse_file(&cached, contents, len))) { if (save_submission(&cached, contents, len) != OK) - fprintf(stderr, "ERR: Failed to save your submission!\n"); + ERR("Failed to save your submission!\n"); else printf("Your file was saved with ID %s!\n", cached.hash); } @@ -235,7 +233,7 @@ search_cmd(const char *arg) if (arg && !strcmp(arg, "last")) { if (!cached.valid) { - fprintf(stderr, "ERR: No cached info report available\n"); + ERR("No cached info report available\n"); return; } hash = cached.hash; @@ -244,7 +242,7 @@ search_cmd(const char *arg) } if (!(d = opendir(resultdir))) { - fprintf(stderr, "ERR: Unable to access upload directory!\n"); + ERR("Unable to access upload directory!\n"); return; } @@ -256,14 +254,15 @@ search_cmd(const char *arg) paths[pathc++] = checkp(strdup(de->d_name)); if (pathc == pathcap) { pathcap *= 2; - paths = checkp(realloc(paths, pathcap * sizeof(char*))); + paths = realloc(paths, pathcap * sizeof(char*)); + checkp(paths); } } } closedir(d); if (pathc == 0) { - fprintf(stderr, "ERR: Couldn't find a matching scan result!\n"); + ERR("Couldn't find a matching scan result!\n"); goto cleanup; } @@ -272,16 +271,13 @@ search_cmd(const char *arg) if (strchr(resp, 'q')) break; which = strtoul(resp, &end, 10); if (which >= pathc || which < 0 || *end) { - fprintf(stderr, "ERR: Invalid index!\n"); + ERR("Invalid index!\n"); goto cleanup; } scandir = aprintf("%s/%s", resultdir, paths[which]); - if (handle_download(scandir)) goto cleanup; - - free(scandir); - scandir = NULL; + NFREE(scandir); } cleanup: @@ -301,7 +297,7 @@ list_cmd(const char *arg) DIR *d; if (!loggedin) { - fprintf(stderr, "ERR: Not logged in!\n"); + ERR("Not logged in!\n"); return; } @@ -311,13 +307,12 @@ list_cmd(const char *arg) if (*de->d_name == '.' && !strchr(".", de->d_name[1])) { printf(">> %s\n", de->d_name); path = aprintf("%s/%s/info", resultdir, de->d_name); - if ((f = fopen(path, "r"))) { - if (load_info(&info, f) == OK) - print_info(&info); - else - fprintf(stderr, "ERR: Failed to read saved file info!\n"); - fclose(f); + if ((f = fopen(path, "r")) && load_info(&info, f) == OK) { + print_info(&info); + } else { + ERR("Failed to read saved file info!\n"); } + if (f) fclose(f); free(path); } } @@ -331,7 +326,7 @@ auth_cmd(const char *arg) int ret; if (loggedin) { - fprintf(stderr, "ERR: Already logged in!\n"); + ERR("Already logged in!\n"); return; } @@ -343,7 +338,7 @@ auth_cmd(const char *arg) } else if (ret && errno == EEXIST) { printf("Success!\nWelcome back!\n"); } else { - fprintf(stderr, "ERR: Auth failed!\n"); + ERR("Auth failed!\n"); return; } @@ -364,14 +359,13 @@ cleanexit() int main() { + struct command *c; const char *cmd, *envstr; char *cp, *arg; int exit, i, cmdlen; - if (!(envstr = getenv("RESULTDIR"))) { - fprintf(stderr, "ERR: RESULTDIR not defined\n"); - return 1; - } + if (!(envstr = getenv("RESULTDIR"))) + die("RESULTDIR not defined\n"); resultdir = checkp(strdup(envstr)); @@ -395,14 +389,16 @@ main() cmdlen = cp ? cp - cmd : strlen(cmd); for (i = 0; i < ARRSIZE(commands); i++) { - if (!strncmp(commands[i].name, cmd, cmdlen) - && cmdlen == strlen(commands[i].name)) { - commands[i].func(arg); + c = &commands[i]; + if (!strncmp(c->name, cmd, cmdlen) && !c->name[cmdlen]) { + c->func(arg); break; } } if (i == ARRSIZE(commands) && strlen(cmd) != 0) - fprintf(stderr, "No such command!\n"); + ERR("No such command!\n"); } + + return EXIT_SUCCESS; } diff --git a/src/stlfile.c b/src/stlfile.c @@ -27,7 +27,8 @@ stack_push(struct stack *stack, int v) { if (stack->count == stack->cap) { stack->cap *= 2; - stack->data = checkp(realloc(stack->data, sizeof(int) * stack->cap)); + stack->data = realloc(stack->data, sizeof(int) * stack->cap); + checkp(stack->data); } stack->data[stack->count] = v; @@ -98,7 +99,6 @@ consume_keyword(char **start) for (i = 0; i < ARRSIZE(kwmap); i++) { len = strlen(kwmap[i].str); if (!strncmp(kwmap[i].str, bp, len) && (!bp[len] || isws(bp[len]))) { - // printf("GOT: %s\n", kwmap[i].str); *start = bp + len + (bp[len] ? 1 : 0); return kwmap[i].code; } @@ -107,9 +107,6 @@ consume_keyword(char **start) return KW_UNKNOWN; } -#define PARSE_FAIL(...) \ - do { fprintf(stderr, "FORMAT ERR: " __VA_ARGS__); goto fail; } while (0) - int parse_file_ascii(struct parseinfo *info, char *buf, size_t len) { @@ -135,81 +132,113 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) switch (kw) { case KW_SOLID_BEGIN: stack_push(&states, STATE_SOLID); - if (stack_ind(&states, KW_SOLID_BEGIN) != -1) - PARSE_FAIL("Multiple nested solids!\n"); + if (stack_ind(&states, KW_SOLID_BEGIN) != -1) { + FMT_ERR("Multiple nested solids!\n"); + goto format_error; + } tmp = bp; - if (!consume_keyword(&bp) && (arg = consume_arg(&bp, &end))) { + if (!consume_keyword(&bp) + && (arg = consume_arg(&bp, &end))) { info->solidname = strndup(arg, end - arg); } else { bp = tmp; } break; case KW_SOLID_END: - if ((kw = stack_pop(&states)) != STATE_SOLID) - PARSE_FAIL("Improper nesting, parent: %s\n", kwmap[kw].str); + if ((kw = stack_pop(&states)) != STATE_SOLID) { + FMT_ERR("Improper nesting, parent: %s\n", + kwmap[kw].str); + goto format_error; + } tmp = bp; if (info->solidname && !consume_keyword(&bp) && (arg = consume_arg(&bp, &end))) { - if (strncmp(info->solidname, arg, end - arg)) - PARSE_FAIL("Solid end/begin names do not match!\n"); + if (strncmp(info->solidname, arg, end - arg)) { + FMT_ERR("Solid names do not match!\n"); + goto format_error; + } } else { bp = tmp; } break; case KW_LOOP_BEGIN: stack_push(&states, STATE_LOOP); - if (stack_ind(&states, KW_LOOP_BEGIN) != -1) - PARSE_FAIL("Multiple nested loops!\n"); + if (stack_ind(&states, KW_LOOP_BEGIN) != -1) { + FMT_ERR("Multiple nested loops!\n"); + goto format_error; + } break; case KW_LOOP_END: - if ((kw = stack_pop(&states)) != STATE_LOOP) - PARSE_FAIL("Improper nesting, parent: %s\n", kwmap[kw].str); + if ((kw = stack_pop(&states)) != STATE_LOOP) { + FMT_ERR("Improper nesting, parent: %s\n", + kwmap[kw].str); + goto format_error; + } info->loopcount++; break; case KW_FACET_BEGIN: stack_push(&states, STATE_FACET); - if (stack_ind(&states, KW_LOOP_BEGIN) != -1) - PARSE_FAIL("Multiple nested facets!\n"); + if (stack_ind(&states, KW_LOOP_BEGIN) != -1) { + FMT_ERR("Multiple nested facets!\n"); + goto format_error; + } for (i = 0; i < 3; i++) { - if (!(arg = consume_arg(&bp, &end))) - PARSE_FAIL("Facet with less than 3 args!\n"); + if (!(arg = consume_arg(&bp, &end))) { + FMT_ERR("Facet with < 3 args!\n"); + goto format_error; + } farg = strtof(arg, &tmp); - if (!isws(*tmp)) - PARSE_FAIL("Facet with invalid arg '%s'!\n", arg); + if (!isws(*tmp)) { + FMT_ERR("Facet arg '%s'\n", arg); + goto format_error; + } } break; case KW_FACET_END: - if ((kw = stack_pop(&states)) != STATE_FACET) - PARSE_FAIL("Improper nesting, parent: %s\n", kwmap[kw].str); + if ((kw = stack_pop(&states)) != STATE_FACET) { + FMT_ERR("Improper nesting, parent: %s\n", + kwmap[kw].str); + goto format_error; + } break; case KW_VERTEX: for (i = 0; i < 3; i++) { - if (!(arg = consume_arg(&bp, &end))) - PARSE_FAIL("Vertex with less than 3 args!\n"); + if (!(arg = consume_arg(&bp, &end))) { + FMT_ERR("Vertex with < 3 args\n"); + goto format_error; + } farg = strtof(arg, &tmp); - if (!isws(*tmp)) - PARSE_FAIL("Vertex with invalid arg '%s'!\n", arg); + if (!isws(*tmp)) { + FMT_ERR("Vertex arg '%s'\n", arg); + goto format_error; + } info->bbmin[i] = MIN(info->bbmin[i], farg); info->bbmax[i] = MAX(info->bbmax[i], farg); } break; case KW_UNKNOWN: prev = skipws(prev); - PARSE_FAIL("Expected keyword, got:\n%.*s...\n", 30, prev); + FMT_ERR("Expected keyword, got:\n%.*s...\n", 30, prev); + goto format_error; } prev = bp; } - if (states.count) - PARSE_FAIL("Expected keyword, got:\n%.*s...\n", 30, bp); + if (states.count) { + FMT_ERR("Expected keyword, got:\n%.*s...\n", 30, bp); + goto format_error; + } bp = skipws(bp); - if (*bp) PARSE_FAIL("Extraneous data at end of file\n"); + if (*bp) { + FMT_ERR("Extraneous data at end of file\n"); + goto format_error; + } stack_free(&states); return OK; -fail: +format_error: stack_free(&states); return FAIL; } @@ -223,8 +252,10 @@ parse_file_bin(struct parseinfo *info, char *buf, size_t len) info->type = TYPE_BIN; - if (len < 84) - PARSE_FAIL("Truncated data! (header missing)\n"); + if (len < 84) { + FMT_ERR("Truncated data! (header missing)\n"); + goto fail; + } memcpy(info->header, buf, 80); @@ -248,12 +279,16 @@ parse_file_bin(struct parseinfo *info, char *buf, size_t len) } for (i = 0; i < info->loopcount; i++) { - if (bp + 50 > end) - PARSE_FAIL("Truncated data! (loops missing)\n"); + if (bp + 50 > end) { + FMT_ERR("Truncated data! (loops missing)\n"); + goto fail; + } for (k = 0; k < 12; k++, bp += 4) { v = fle32toh(*(float*)bp); - if (v == INFINITY || v == NAN) - PARSE_FAIL("Encountered invalid float\n"); + if (v == INFINITY || v == NAN) { + FMT_ERR("Encountered invalid float\n"); + goto fail; + } if (k >= 3) { info->bbmin[k % 3] = MIN(info->bbmin[k % 3], v); info->bbmax[k % 3] = MAX(info->bbmax[k % 3], v); @@ -262,11 +297,15 @@ parse_file_bin(struct parseinfo *info, char *buf, size_t len) bp += 2; } - if (bp != end) PARSE_FAIL("Extraneous data at end of file\n"); + if (bp != end) { + FMT_ERR("Extraneous data at end of file\n"); + goto fail; + } return OK; fail: + NFREE(info->solidname); return FAIL; } @@ -277,10 +316,10 @@ parse_file(struct parseinfo *info, char *buf, size_t len) const char *resp; char *bp; - if (info->valid) free_info(info); + free_info(info); if (len < 10) { - fprintf(stderr, "ERR: File too small!\n"); + ERR("File too small!\n"); return FAIL; } @@ -298,7 +337,7 @@ parse_file(struct parseinfo *info, char *buf, size_t len) if (!info->modelname) { resp = ask("Please enter your model name: "); if (strlen(resp) < 4) { - fprintf(stderr, "ERR: Model name is too short!\n"); + ERR("Model name is too short!\n"); return FAIL; } info->modelname = checkp(strdup(resp)); @@ -404,9 +443,9 @@ print_info(struct parseinfo *info) void free_info(struct parseinfo *info) { - NULLFREE(info->hash); - NULLFREE(info->modelname); - NULLFREE(info->solidname); + NFREE(info->hash); + NFREE(info->modelname); + NFREE(info->solidname); info->valid = 0; } diff --git a/src/stlfile.h b/src/stlfile.h @@ -9,6 +9,8 @@ #include "util.h" +#define FMT_ERR(...) ERR("FORMAT " __VA_ARGS__) + enum { KW_INVALID = -1, KW_UNKNOWN, diff --git a/src/util.h b/src/util.h @@ -11,7 +11,10 @@ #define MIN(x,y) ((x) > (y) ? (y) : (x)) #define MAX(x,y) ((x) < (y) ? (y) : (x)) -#define NULLFREE(p) do { free(p); p = NULL; } while (0) +#define ERR(...) fprintf(stderr, "ERR: " __VA_ARGS__) + +#define NFREE(p) do { free(p); p = NULL; } while (0) +#define NFCLOSE(f) do { fclose(f); f = NULL; } while (0) #define MHASHLEN 40