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;
- }
-}