diff --git a/src/include/io.h b/src/include/io.h new file mode 100644 index 0000000..33fac4b --- /dev/null +++ b/src/include/io.h @@ -0,0 +1,29 @@ +/* + ncdg - A program to help generate natechoe.dev + Copyright (C) 2022 Nate Choe (natechoe9@gmail.com) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include + +struct linefile { + char *prevline; + FILE *file; +}; + +void ungetline(struct linefile *file, char *line); +char *getline(struct linefile *file); +struct linefile *newlinefile(FILE *file); +void freelinefile(struct linefile *file); diff --git a/src/io.c b/src/io.c new file mode 100644 index 0000000..f5f394e --- /dev/null +++ b/src/io.c @@ -0,0 +1,83 @@ +#include +#include + +#include + +static char *append(char *str, char c, size_t *len, size_t *alloc); + +void ungetline(struct linefile *file, char *line) { + file->prevline = line; +} + +char *getline(struct linefile *file) { + size_t alloc; + size_t len; + char *ret; + int c; + + if (file->prevline != NULL) { + ret = file->prevline; + file->prevline = NULL; + return ret; + } + + c = fgetc(file->file); + if (c == EOF) + return NULL; + ungetc(c, file->file); + + alloc = 80; + len = 0; + ret = malloc(alloc); + if (ret == NULL) + return NULL; + + for (;;) { + c = fgetc(file->file); + if (c == '\n') { + ret[len] = '\0'; + return ret; + } + if (c == '\t') { + while (len % 4 != 0) { + ret = append(ret, ' ', &len, &alloc); + if (ret == NULL) + return NULL; + } + } + else { + ret = append(ret, c, &len, &alloc); + if (ret == NULL) + return NULL; + } + } +} + +struct linefile *newlinefile(FILE *file) { + struct linefile *ret; + ret = malloc(sizeof *ret); + ret->prevline = NULL; + ret->file = file; + return ret; +} + +void freelinefile(struct linefile *file) { + free(file->prevline); + fclose(file->file); + free(file); +} + +static char *append(char *str, char c, size_t *len, size_t *alloc) { + if (*len >= *alloc) { + char *newstr; + *alloc *= 2; + newstr = realloc(str, *alloc); + if (newstr == NULL) { + free(str); + return NULL; + } + str = newstr; + } + str[(*len)++] = c; + return str; +} diff --git a/src/template.c b/src/template.c index 0b0ee40..f58fea8 100644 --- a/src/template.c +++ b/src/template.c @@ -20,13 +20,9 @@ #include #include +#include #include -struct linefile { - char *prevline; - FILE *file; -}; - enum paratype { NORMAL, EMPTY, @@ -85,16 +81,13 @@ static int writeescape(char c, FILE *outfile); static int writedata(char *data, size_t len, FILE *outfile); static int writesimple(char *data, size_t len, FILE *outfile); -static void ungetline(struct linefile *file, char *line); -static char *getline(struct linefile *file); - static const char *escapedchars = "!\"#%&'()*,./:;?@[\\]^{|}~"; int parsetemplate(FILE *infile, FILE *outfile) { - struct linefile realin; - realin.prevline = NULL; - realin.file = infile; - while (parsepara(&realin, outfile) == 0) ; + struct linefile *realin; + realin = newlinefile(infile); + while (parsepara(realin, outfile) == 0) ; + freelinefile(realin); return 0; } @@ -531,50 +524,3 @@ static int writesimple(char *data, size_t len, FILE *outfile) { } return 0; } - -static void ungetline(struct linefile *file, char *line) { - file->prevline = line; -} - -static char *getline(struct linefile *file) { - size_t alloc; - size_t len; - char *ret; - int c; - - if (file->prevline != NULL) { - ret = file->prevline; - file->prevline = NULL; - return ret; - } - - c = fgetc(file->file); - if (c == EOF) - return NULL; - ungetc(c, file->file); - - alloc = 80; - len = 0; - ret = malloc(alloc); - if (ret == NULL) - return NULL; - - for (;;) { - if (len >= alloc) { - char *newret; - alloc *= 2; - newret = realloc(ret, alloc); - if (newret == NULL) { - free(ret); - return NULL; - } - ret = newret; - } - c = fgetc(file->file); - if (c == '\n') { - ret[len] = '\0'; - return ret; - } - ret[len++] = c; - } -}