aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2022-10-23 17:23:10 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2022-10-23 17:23:14 -0400
commitdfbeefbc98a5e922483c2970fcdaf6197872dec8 (patch)
tree645ee1d42db52be9453dd9495faa78c8a9adf791
parent2b295e0b12f417ec9756fef9bd615e3ded06cccd (diff)
downloadsayeth-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
-rw-r--r--main.c140
1 files changed, 100 insertions, 40 deletions
diff --git a/main.c b/main.c
index 70c1bb5..93d0ed8 100644
--- a/main.c
+++ b/main.c
@@ -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;
}