summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinnnus <[email protected]>2024-02-17 00:26:40 +0100
committerLinnnus <[email protected]>2024-02-17 00:47:08 +0100
commitad937750d754676f8e9e01ce2c1021ad1a80ee04 (patch)
tree470920cffe3d30f466ba837b68ac885a1a9f0aef
parentdd4f820139f81ae5013824f24c5392b567562c41 (diff)
feat: Add creole utility
This patch a) gives the different binaries' main() files more meaning full names and b) adds the creole binary, which works like smu except for my dialect of Creole (which should hopefully approach proper Creole as this repo matures).
-rw-r--r--Makefile18
-rw-r--r--flake.nix10
-rw-r--r--src/creole_test_main.c (renamed from src/creole-test.c)0
-rw-r--r--src/creole_util_main.c108
-rw-r--r--src/simplewiki_main.c (renamed from src/main.c)0
5 files changed, 126 insertions, 10 deletions
diff --git a/Makefile b/Makefile
index 7520811..be87da4 100644
--- a/Makefile
+++ b/Makefile
@@ -11,30 +11,36 @@ PREFIX ?= /usr/local
all: build/simplewiki
-install: build/simplewiki
+install: build/simplewiki build/creole
mkdir -p $(PREFIX)/bin
mkdir -p $(PREFIX)/share/man/man1
cp -f build/simplewiki $(PREFIX)/bin
+ cp -f build/creole $(PREFIX)/bin
gzip <doc/simplewiki.1 >$(PREFIX)/share/man/man1/simplewiki.1.gz
uninstall:
rm -f $(PREFIX)/bin/simplewiki
+ rm -f $(PREFIX)/bin/creole
rm -f $(PREFIX)/share/man/man1/simplewiki.1.gz
rmdir $(PREFIX)/bin >/dev/null 2>&1 || true
rmdir $(PREFIX)/share/man/man1 >/dev/null 2>&1 || true
-build/simplewiki: build/main.o build/die.o build/arena.o build/strutil.o build/creole.o
- $(CC) $(CFLAGS) $(LDFLAGS) -o build/simplewiki $^ $(LDLIBS)
+build/simplewiki: build/simplewiki_main.o build/die.o build/arena.o build/strutil.o build/creole.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
-build/creole-test: build/creole-test.o build/creole.o
+build/creole_test: build/creole_test_main.o build/creole.o
$(CC) $(CFLAGS) -o $@ $^
-build/creole-test.o: src/creole-test.c
-build/main.o: src/main.c src/arena.h src/die.h src/strutil.h src/creole.h
+build/creole: build/creole_util_main.o build/creole.o
+ $(CC) $(CFLAGS) -o $@ $^
+
+build/creole_test_main.o: src/creole_test_main.c
+build/simplewiki_main.o: src/simplewiki_main.c src/arena.h src/die.h src/strutil.h src/creole.h
build/arena.o: src/arena.c src/arena.h
build/die.o: src/die.c src/die.h
build/strutil.o: src/strutil.c src/strutil.h src/arena.h
build/creole.o: src/creole.c
+build/creole_util_main.o: src/creole_util_main.c src/creole.h
build/%.o: src/%.c | build/
$(CC) $(CFLAGS) -c -o $@ $<
diff --git a/flake.nix b/flake.nix
index 1341dd9..ba4c2cd 100644
--- a/flake.nix
+++ b/flake.nix
@@ -39,14 +39,16 @@
src = ./.;
- nativeBuildInputs = with pkgs; [ pkg-config ];
- buildInputs = with pkgs; [ libgit2 ];
+ buildPhase = ''
+ make build/creole_test
+ '';
installPhase = ''
mkdir -p $out/bin
- make build/creole-test
- mv build/creole-test $out/bin
+ mv build/creole_test $out/bin
'';
+
+ meta.mainProgram = "creole_test";
};
devShell = (pkgs.mkShell.override { inherit stdenv; }) {
diff --git a/src/creole-test.c b/src/creole_test_main.c
index 1157721..1157721 100644
--- a/src/creole-test.c
+++ b/src/creole_test_main.c
diff --git a/src/creole_util_main.c b/src/creole_util_main.c
new file mode 100644
index 0000000..7d29c68
--- /dev/null
+++ b/src/creole_util_main.c
@@ -0,0 +1,108 @@
+#include "creole.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define CHUNK_SIZE 128
+
+int read_file(const char *file_path, char **out_buffer, size_t *out_length) {
+ assert(out_buffer != NULL && *out_buffer == NULL);
+ assert(file_path != NULL);
+
+ FILE *fp = fopen(file_path, "r");
+ if (fp == NULL) {
+ return -1;
+ }
+
+ char *buffer = NULL;
+ size_t allocated = 0;
+ size_t used = 0;
+ while (true) {
+ // Grow buffer, if needed.
+ if (used + CHUNK_SIZE > allocated) {
+ // Grow exponentially to guarantee O(log(n)) performance.
+ allocated = (allocated == 0) ? CHUNK_SIZE : allocated * 2;
+
+ // Overflow check. Some ANSI C compilers may optimize this away, though.
+ if (allocated <= used) {
+ free(buffer);
+ fclose(fp);
+ errno = EOVERFLOW;
+ return -1;
+ }
+
+ char *temp = realloc(buffer, allocated);
+ if (temp == NULL) {
+ int old_errno = errno;
+ free(buffer); // free() may not set errno
+ fclose(fp); // fclose() may set errno
+ errno = old_errno;
+ return -1;
+ }
+ buffer = temp;
+ }
+
+ size_t nread = fread(buffer + used, 1, CHUNK_SIZE, fp);
+ if (nread == 0) {
+ // End-of-file or errnor has occured.
+ // FIXME: Should we be checking (nread < CHUNK_SIZE)?
+ // https://stackoverflow.com/a/39322170
+ break;
+ }
+ used += nread;
+ }
+
+ if (ferror(fp)) {
+ int old_errno = errno;
+ free(buffer); // free() may not set errno
+ fclose(fp); // fclose() may set errno
+ errno = old_errno;
+ return -1;
+ }
+
+ // Reallocate to optimal size.
+ char *temp = realloc(buffer, used + 1);
+ if (temp == NULL) {
+ int old_errno = errno;
+ free(buffer); // free() may not set errno
+ fclose(fp); // fclose() may set errno
+ errno = old_errno;
+ return -1;
+ }
+ buffer = temp;
+
+ // Null-terminate the buffer. Note that buffers may still contain \0,
+ // so strlen(buffer) == length may not be true.
+ buffer[used] = '\0';
+
+ // Return buffer.
+ *out_buffer = buffer;
+ if (out_length != NULL) {
+ *out_length = used;
+ }
+ fclose(fp);
+ return 0;
+}
+
+int main(void) {
+ size_t buffer_length = 0;
+ char *buffer = NULL;
+ if (read_file("/dev/stdin", &buffer, &buffer_length) < 0) {
+ perror("Failed to read stdin");
+ return EXIT_FAILURE;
+ }
+
+ render_creole(stdout, buffer, buffer_length);
+
+ // The lack of return value makes it painfully obvious that we aren't
+ // handling errors at all. This represents my half-hearted attempt to fix that.
+ if (ferror(stdout)) {
+ perror("Failed to write to stdout");
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/main.c b/src/simplewiki_main.c
index 5c04467..5c04467 100644
--- a/src/main.c
+++ b/src/simplewiki_main.c