about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Makefile17
-rw-r--r--README.md28
-rw-r--r--cat.c34
-rw-r--r--md2html.c322
4 files changed, 346 insertions, 55 deletions
diff --git a/Makefile b/Makefile
index f0d9e30..cccffaf 100644
--- a/Makefile
+++ b/Makefile
@@ -2,13 +2,18 @@ CC=gcc
 CC_OPTS=-g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone -fno-omit-frame-pointer -pg -mnop-mcount
 INCLUDE=-fuse-ld=bfd -Wl,-T,ape/ape.lds -include ape/cosmopolitan.h ape/crt.o ape/ape.o ape/cosmopolitan.a
 
-all: cat.com
+NAME=md2html
 
-cat.com.dbg: cat.c
-	$(CC) $(CC_OPTS) cat.c -o cat.com.dbg $(INCLUDE)
+all: $(NAME).com
 
-cat.com: cat.com.dbg
-	objcopy -S -O binary cat.com.dbg cat.com
+$(NAME).com.dbg: $(NAME).c
+	$(CC) $(CC_OPTS) $(NAME).c -o $(NAME).com.dbg $(INCLUDE)
+
+$(NAME).com: $(NAME).com.dbg
+	objcopy -S -O binary $(NAME).com.dbg $(NAME).com
 
 clean:
-	rm cat.com cat.com.dbg
+	rm $(NAME).com $(NAME).com.dbg
+
+deploy: $(NAME).com
+	scp $(NAME).com srv1:/var/www/niedzwiedzinski.cyou/$(NAME).com
diff --git a/README.md b/README.md
index 7a93879..90c0adb 100644
--- a/README.md
+++ b/README.md
@@ -1,34 +1,32 @@
-# cat
+# md2html
 
-This is a simple C program that outputs file content. The magic is that it works
-on Linux, *BSD, macOs, Windows thanks to [cosmopolitan](https://github.com/jart/cosmopolitan).
+> Markdown to html renderer that works on Windows
 
-I created this repo as a project template for simple ape programs. `/ape` folder
-contains https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-0.3.zip and
-`/stdio` is copied from cosmopolitan@7ed524ca31bca83fe6700045d346cad3f97b9567
+Fork of [md2html](https://github.com/kukrimate/md2html). The magic is that it works
+on Linux, *BSD, macOs, Windows thanks to [cosmopolitan](https://github.com/jart/cosmopolitan).
 
 ## Running
 
 ```sh
-wget https://niedzwiedzinski.cyou/cat.com
-chmod +x cat.com
-sha256sum cat.com
-# 495b3bb169813b07d4c4c43568c6c395e72a952fdf7fe3e5b46bf130cc415af0
+wget https://niedzwiedzinski.cyou/md2htmmd2html.com
+chmod +x md2html.com
+sha256sum md2html.com
+# 0f1477ae8abfbc9c973d5149a63e5fe33d5121d515de2c9379e29bca42736d1c
 
 # For zsh or fish
-bash -c "./cat.com"
+bash -c "./md2html.com"
 
 # For everything else
-./cat.com
+./md2html.com
 ```
 
 ## Compiling
 
 Requirements:
 
-- make
-- gcc
-- objcopy (from pkg `binutils`)
+* make
+* gcc
+* objcopy (from pkg `binutils`)
 
 ```
 make
diff --git a/cat.c b/cat.c
deleted file mode 100644
index 92a19b7..0000000
--- a/cat.c
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "stdio/stdio.h"
-
-int cat(char* filename) {
-  FILE *f;
-  f = fopen(filename, "r");
-  if (f == NULL) {
-    printf("Cannot open file '%s'\n", filename);
-    return 1;
-  }
-
-  char *line = NULL;
-  size_t linecap = 0;
-  ssize_t linelen;
-  while ((linelen = getline(&line, &linecap, f)) != -1) {
-    printf("%s", line);
-  }
-  free(line);
-  fclose(f);
-  return 0;
-}
-
-int main(int argc, char *argv[]) {
-  int err = 0;
-
-  if (argc > 1) {
-    for (int i = 1; i < argc; i++) {
-      cat(argv[i]);
-    }
-  } else {
-    printf("Usage: cat FILE [FILE] ...\n");
-  }
-
-  return 0;
-}
diff --git a/md2html.c b/md2html.c
new file mode 100644
index 0000000..ab78ad1
--- /dev/null
+++ b/md2html.c
@@ -0,0 +1,322 @@
+/*
+ * Source: https://github.com/kukrimate/md2html
+ *
+ * Copyright (c) 2020, Máté Kukri
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "stdio/stdio.h"
+
+int
+peak(FILE *fp)
+{
+	int ch;
+
+	ungetc((ch = fgetc(fp)), fp);
+	return ch;
+}
+
+int
+next(FILE *fp, int want)
+{
+	int ch;
+
+	ch = fgetc(fp);
+	if (ch != want)
+		ungetc(ch, fp);
+	return ch;
+}
+
+char *
+nextstr(FILE *fp, char *want)
+{
+	char *cur;
+	int ch;
+
+	for (cur = want; *cur; ++cur)
+		if ((ch = fgetc(fp)) != *cur)
+			goto fail;
+	return want;
+fail:
+	ungetc(ch, fp);
+	while (--cur >= want)
+		ungetc(*cur, fp);
+	return NULL;
+}
+
+void
+skip_white(FILE *fp)
+{
+	int ch;
+
+	while ((ch = fgetc(fp)) != EOF)
+		switch (ch) {
+		case ' ':
+		case '\t':
+		case '\r':
+		case '\n':
+		case '\v':
+		case '\f':
+			break;
+		default:
+			ungetc(ch, fp);
+			return;
+		}
+}
+
+void
+code(FILE *fp)
+{
+	int ch;
+
+	printf("<code>");
+	while ((ch = fgetc(fp)) != EOF)
+		switch (ch) {
+		case '`':
+			goto end;
+		default:
+			putchar(ch);
+		}
+end:
+	printf("</code>");
+}
+
+void
+esccode(FILE *fp)
+{
+	int ch;
+
+	printf("<code>");
+	while ((ch = fgetc(fp)) != EOF)
+		switch (ch) {
+		case '`':
+			if (next(fp, '`') == '`')
+				goto end;
+		default:
+			putchar(ch);
+		}
+end:
+	printf("</code>");
+}
+
+void
+codeblock(FILE *fp)
+{
+	int ch;
+
+	skip_white(fp);
+	printf("<pre><code>");
+	while ((ch = fgetc(fp)) != EOF)
+		switch (ch) {
+		case '`':
+			if (nextstr(fp, "``"))
+				goto end;
+		default:
+			putchar(ch);
+		}
+end:
+	printf("</code></pre>\n");
+}
+
+void
+heading(FILE *fp, int lvl)
+{
+	int ch;
+
+	skip_white(fp);
+	printf("<h%d>", lvl);
+	while ((ch = fgetc(fp)) != EOF)
+		switch (ch) {
+		/* End of heading */
+		case '\n':
+			goto end;
+		default:
+			putchar(ch);
+		}
+end:
+	printf("</h%d>\n", lvl);
+}
+
+void
+blockquote(FILE *fp)
+{
+	int ch;
+
+	printf("<blockquote>");
+	while ((ch = fgetc(fp)) != EOF)
+		switch (ch) {
+		case '\n':
+			/* End of blockquote */
+			if (next(fp, '\n') == '\n')
+				goto end;
+
+			/* Next top level element */
+			switch (peak(fp)) {
+			case '#': /* Heading */
+			case '*': /* List */
+				goto end;
+			case '`': /* Code block */
+				if (nextstr(fp, "```")) {
+					ungetc('`', fp);
+					ungetc('`', fp);
+					ungetc('`', fp);
+					goto end;
+				}
+			}
+
+			/* Ignore > on subsequent lines */
+			if (next(fp, '>') == '>')
+				break;
+		default:
+			putchar(ch);
+		}
+end:
+	printf("</blockquote>\n");
+}
+
+void
+list(FILE *fp)
+{
+	int ch;
+
+	printf("<ul><li>");
+
+	while ((ch = fgetc(fp)) != EOF)
+		switch (ch) {
+		case '\n':
+			/* End of list */
+			if (next(fp, '\n') == '\n')
+				goto end;
+
+			/* Next top level element */
+			switch (peak(fp)) {
+			case '#': /* Heading */
+			case '>': /* Blockquote */
+				goto end;
+			case '`': /* Code block */
+				if (nextstr(fp, "```")) {
+					ungetc('`', fp);
+					ungetc('`', fp);
+					ungetc('`', fp);
+					goto end;
+				}
+			}
+
+			/* Line starting with * means next element */
+			if (next(fp, '*') == '*') {
+				printf("</li><li>");
+				break;
+			}
+		default:
+			putchar(ch);
+		}
+
+end:
+	printf("</li></ul>\n");
+}
+
+void
+paragraph(FILE *fp)
+{
+	int ch;
+
+	printf("<p>");
+	while ((ch = fgetc(fp)) != EOF)
+		switch (ch) {
+		case '`':
+			if (next(fp, '`') == '`')	/* Escaped code */
+				esccode(fp);
+			else				/* Normal code */
+				code(fp);
+			break;
+		case '\n':
+			/* End of paragraph */
+			if (next(fp, '\n') == '\n')
+				goto end;
+
+			/* Next top level element */
+			switch (peak(fp)) {
+			case '#': /* Heading */
+			case '>': /* Blockquote */
+			case '*': /* List */
+				goto end;
+			case '`': /* Code block */
+				if (nextstr(fp, "```")) {
+					ungetc('`', fp);
+					ungetc('`', fp);
+					ungetc('`', fp);
+					goto end;
+				}
+			}
+		default:
+			putchar(ch);
+		}
+
+end:
+	printf("</p>\n");
+}
+
+void
+md2html(FILE *fp)
+{
+	int ch, cnt;
+
+	for (;;)
+		switch ((ch = fgetc(fp))) {
+		case EOF:
+			return;
+		/* Consume newlines at the start of top level blocks */
+		case '\n':
+			break;
+		case '#':
+			cnt = 1;
+			while (next(fp, '#') == '#')
+				++cnt;
+			heading(fp, cnt);
+			break;
+		case '>':
+			blockquote(fp);
+			break;
+		case '*':
+			list(fp);
+			break;
+		case '`':
+			if (nextstr(fp, "``")) {
+				codeblock(fp);
+				break;
+			}
+		default:
+			ungetc(ch, fp);
+			paragraph(fp);
+		}
+}
+
+int
+main(int argc, char *argv[])
+{
+	FILE *fp;
+
+	if (argc < 2) {
+		fp = stdin;
+	} else {
+		if (!(fp = fopen(argv[1], "r"))) {
+			perror(argv[1]);
+			return 1;
+		}
+	}
+
+	md2html(fp);
+	fclose(fp);
+	return 0;
+}