summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bin/edi/edi.c4
-rw-r--r--bin/edi/edi.h5
-rw-r--r--bin/edi/file.c32
3 files changed, 39 insertions, 2 deletions
diff --git a/bin/edi/edi.c b/bin/edi/edi.c
index fb6e3929..3a52e228 100644
--- a/bin/edi/edi.c
+++ b/bin/edi/edi.c
@@ -29,10 +29,12 @@ int main(int argc, char *argv[]) {
 	struct File file = fileAlloc(strdup(argv[1]));
 	fileRead(&file);
 
-	const struct Table *table = &file.log.states[file.log.state].table;
+	const struct Table *table = logTable(&file.log);
 	for (struct Iter it = iter(table, 0); it.ch != WEOF; it = iterNext(it)) {
 		printf("%lc", it.ch);
 	}
 
+	fileWrite(&file);
+
 	fileFree(&file);
 }
diff --git a/bin/edi/edi.h b/bin/edi/edi.h
index 644e0901..ee1fdd4a 100644
--- a/bin/edi/edi.h
+++ b/bin/edi/edi.h
@@ -82,6 +82,10 @@ struct Log {
 struct Log logAlloc(size_t cap);
 void logFree(struct Log *log);
 void logPush(struct Log *log, struct Table table);
+static inline struct Table *logTable(const struct Log *log) {
+	if (log->state == log->len) return NULL;
+	return &log->states[log->state].table;
+}
 
 struct File {
 	char *path;
@@ -92,3 +96,4 @@ struct File {
 struct File fileAlloc(char *path);
 void fileFree(struct File *file);
 void fileRead(struct File *file);
+void fileWrite(struct File *file);
diff --git a/bin/edi/file.c b/bin/edi/file.c
index 85984aee..7f9fef45 100644
--- a/bin/edi/file.c
+++ b/bin/edi/file.c
@@ -14,7 +14,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <assert.h>
 #include <err.h>
 #include <errno.h>
 #include <stdio.h>
@@ -80,3 +79,34 @@ void fileRead(struct File *file) {
 
 	fclose(stream);
 }
+
+// TODO: Error handling.
+void fileWrite(struct File *file) {
+	if (!file->path) return;
+
+	FILE *stream = fopen(file->path, "w");
+	if (!stream) err(EX_CANTCREAT, "%s", file->path);
+
+	const struct Table *table = logTable(&file->log);
+	if (!table) errx(EX_SOFTWARE, "fileWrite: no table");
+
+	char buf[BufferCap];
+	mbstate_t state = StateInit;
+	for (size_t i = 0; i < table->len; ++i) {
+		struct Slice slice = table->slices[i];
+		while (slice.len) {
+			size_t mbsLen = wcsnrtombs(
+				buf, &slice.ptr, slice.len, sizeof(buf), &state
+			);
+			if (mbsLen == (size_t)-1) err(EX_DATAERR, "%s", file->path);
+			slice.len -= slice.ptr - table->slices[i].ptr;
+
+			fwrite(buf, 1, mbsLen, stream);
+			if (ferror(stream)) err(EX_IOERR, "%s", file->path);
+		}
+	}
+	file->clean = file->log.state;
+
+	fclose(stream);
+	if (ferror(stream)) err(EX_IOERR, "%s", file->path);
+}