diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2022-10-23 17:23:10 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2022-10-23 17:23:14 -0400 |
commit | dfbeefbc98a5e922483c2970fcdaf6197872dec8 (patch) | |
tree | 645ee1d42db52be9453dd9495faa78c8a9adf791 /main.c | |
parent | 2b295e0b12f417ec9756fef9bd615e3ded06cccd (diff) | |
download | sayeth-dfbeefbc98a5e922483c2970fcdaf6197872dec8.tar.gz |
Fixups
* Fix indentation
* Draw art outside of the driver
* Move globals up to the top
* Fix buffer overflow(s)
* Free driver memory
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 140 |
1 files changed, 100 insertions, 40 deletions
@@ -12,8 +12,11 @@ #define DATA_BUFSIZ 8192 #define DRIVERS_ALLOC_DEFAULT 128 -size_t START_Y = 0; +size_t START_Y_BOX = 0; +size_t START_Y_CARET = 0; +size_t START_Y_DATA = 0; const char *A_TAB = " "; +char wspace = ' '; char box_top_left = '\0'; char box_top = '\0'; char box_top_right = '\0'; @@ -22,6 +25,22 @@ char box_bottom_left = '\0'; char box_bottom = '\0'; char box_bottom_right = '\0'; +struct Driver { + char *name; + size_t box_indent; + char *box_elements; + size_t caret_pos; + size_t caret_indent; + size_t caret_attached; + char *caret; + size_t data_indent; + char *data; +}; +struct Driver **drivers = NULL; +size_t drivers_alloc = DRIVERS_ALLOC_DEFAULT; +size_t drivers_used = 0; + + void repchar(char ch, size_t limit) { while (limit > 0) { putc(ch, stdout); @@ -58,26 +77,26 @@ size_t get_longest_line(char *s) { } void box_draw_top(size_t y, size_t longest) { - repchar(' ', y); + repchar(wspace, y); repchar(box_top_left, 1); repchar(box_top, longest); repchar(box_top_right, 1); } void box_draw_bottom(size_t y, size_t longest) { - repchar(' ', y); + repchar(wspace, y); repchar(box_bottom_left, 1); repchar(box_bottom, longest); repchar(box_bottom_right, 1); } void box_draw_next_line(size_t y) { - repchar(' ', y); + repchar(wspace, y); repchar(box_side, 1); } void box_draw_end_line(size_t longest, size_t len) { - repchar(' ', longest - len); + repchar(wspace, longest - len); repchar(box_side, 1); } @@ -102,7 +121,7 @@ int boxprintf(const char *fmt, ...) { size_t longest = get_longest_line(output); - box_draw_top(START_Y, longest); + box_draw_top(START_Y_BOX, longest); puts(""); for (size_t i = 0; i < strlen(output); i++) { @@ -112,7 +131,7 @@ int boxprintf(const char *fmt, ...) { } if (len == 0) { - box_draw_next_line(START_Y); + box_draw_next_line(START_Y_BOX); } if (output[i] == '\n') { @@ -127,24 +146,28 @@ int boxprintf(const char *fmt, ...) { len++; } puts(""); - box_draw_bottom(START_Y, longest); + box_draw_bottom(START_Y_BOX, longest); va_end(list); return count; } void usage(char *prog) { - printf("usage: %s [-d driver_name] [-] {input}\n" + printf("usage: %s [-d driver_name] [-w] [-] {input}\n" "-h Show this help message\n" "-d Driver name (fierrhea, jenkins, romero)\n" + "-w Show indentation whitespace\n" "\n" "- Read from standard input\n" "input A quoted string\n", prog); } void caret_draw(char *data, size_t indent, size_t attached) { + if (!strlen(data)) + return; + if (!attached) - repchar(' ', START_Y); + repchar(wspace, START_Y_BOX); for (size_t i = 0; i < strlen(data); i++) { if (data[i] == '\\' && isalpha(data[i + 1])) { @@ -152,29 +175,19 @@ void caret_draw(char *data, size_t indent, size_t attached) { switch (data[i]) { case 'n': putc('\n', stdout); - if (i < strlen(data) - 1) - i++; - repchar(' ', indent); - break; + if (i == strlen(data) - 1) + continue; + repchar(wspace, indent); + continue; + default: + continue; } } putc(data[i], stdout); } - puts(""); } -struct Driver { - char *name; - size_t box_indent; - char *box_elements; - size_t caret_pos; - size_t caret_indent; - size_t caret_attached; - char *caret; - char *data; -}; - struct Driver *driver_load(char *filename) { FILE *fp = NULL; struct Driver *driver = NULL; @@ -189,8 +202,9 @@ struct Driver *driver_load(char *filename) { return NULL; } - for (size_t i = 0; i < 8; i++) { + for (size_t i = 0; i < 9; i++) { char buf[INPUT_BUFSIZ] = {0}; + ssize_t lastpos = ftell(fp); if (fgets(buf, sizeof(buf) - 1, fp) == NULL) { break; } @@ -234,13 +248,17 @@ struct Driver *driver_load(char *filename) { } break; case 7: + driver->data_indent = strtol(buf, 0, 10); + break; + case 8: driver->data = calloc(DATA_BUFSIZ, sizeof(*driver->data)); if (!driver->data) { fclose(fp); return NULL; } - fseek(fp, (long)-strlen(buf), SEEK_CUR); - fread(driver->data + strlen(driver->data), 1, DATA_BUFSIZ - 1, fp); + // rewind to beginning of the data section + fseek(fp, lastpos, SEEK_SET); + fread(driver->data, 1, DATA_BUFSIZ - 1, fp); break; default: break; @@ -250,10 +268,6 @@ struct Driver *driver_load(char *filename) { return driver; } -struct Driver **drivers = NULL; -size_t drivers_alloc = DRIVERS_ALLOC_DEFAULT; -size_t drivers_used = 0; - int driver_register(struct Driver *driver) { if (!drivers) { drivers = calloc(drivers_alloc, sizeof(**drivers)); @@ -279,6 +293,41 @@ int driver_register(struct Driver *driver) { return 0; } +void drivers_free(struct Driver **list) { + for (size_t i = 0; i < drivers_alloc; i++) { + if (drivers[i]) { + if (drivers[i]->name) + free(drivers[i]->name); + if (drivers[i]->data) + free(drivers[i]->data); + if (drivers[i]->caret) + free(drivers[i]->caret); + if (drivers[i]->box_elements) + free(drivers[i]->box_elements); + free(drivers[i]); + } + } + free(drivers); +} + +void data_draw(char *data, size_t indent) { + size_t len = 0; + for (size_t i = 0; i < strlen(data); i++) { + if (len == 0) { + repchar(wspace, indent); + } + + if (data[i] == '\n') { + putc('\n', stdout); + len = 0; + continue; + } + + putc(data[i], stdout); + len++; + } +} + void driver_run(struct Driver *driver, char *input) { char *elem = driver->box_elements; box_top_left = elem[0]; @@ -288,18 +337,22 @@ void driver_run(struct Driver *driver, char *input) { box_bottom_left = elem[4]; box_bottom = elem[5]; box_bottom_right = elem[6]; - START_Y = driver->box_indent; + START_Y_BOX = driver->box_indent; + START_Y_CARET = driver->caret_indent; + START_Y_DATA = driver->data_indent; if (!driver->caret_pos) { - boxprintf(input); - caret_draw(driver->caret, driver->caret_indent, driver->caret_attached); + boxprintf("%s", input); + caret_draw(driver->caret, START_Y_CARET, driver->caret_attached); } - printf("%s", driver->data); + if (driver->data) { + data_draw(driver->data, START_Y_DATA); + } if (driver->caret_pos) { - caret_draw(driver->caret, driver->caret_indent, driver->caret_attached); - boxprintf(input); + caret_draw(driver->caret, START_Y_CARET, driver->caret_attached); + boxprintf("%s", input); } } @@ -329,7 +382,7 @@ int main(int argc, char *argv[]) { strcpy(driver_name, "fierrhea"); int option; - while ((option = getopt (argc, argv, "hd:")) != -1) { + while ((option = getopt (argc, argv, "hd:w")) != -1) { switch (option) { case 'h': usage(argv[0]); @@ -337,6 +390,9 @@ int main(int argc, char *argv[]) { case 'd': strcpy(driver_name, optarg); break; + case 'w': + wspace = '.'; + break; case ':': fprintf(stderr, "option requires value\n"); usage(argv[0]); @@ -381,7 +437,9 @@ int main(int argc, char *argv[]) { fprintf(stderr, "unable to register driver: %s (%s)\n", path, strerror(errno)); exit(1); } + free(drv); } + closedir(dir); if (!drivers_used) { fprintf(stderr, "No drivers present in '%s'?\n", driver_dir); @@ -412,5 +470,7 @@ int main(int argc, char *argv[]) { driver_run(driver, input); puts(""); + drivers_free(drivers); + free(driver_dir); return 0; } |