From 5f44aae0f77cb9c8a0be83954cd67c0a650ad36c Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 10 Dec 2017 01:10:04 -0500 Subject: [PATCH] Implement literal sections --- src/main.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++------ diff --git a/src/main.c b/src/main.c index 27b9bca57fef8f83bfa5e5915ddb2c2268b51262..e2865b50842aff2b29c006ac11d99b6a834ec3f8 100644 --- a/src/main.c +++ b/src/main.c @@ -150,19 +150,21 @@ } } } -static int parse_indent(struct parser *p, int *indent) { +static int parse_indent(struct parser *p, int *indent, bool write) { int i = 0; uint32_t ch; while ((ch = parser_getch(p)) == '\t') { ++i; } parser_pushch(p, ch); - if (i == *indent - 1) { - roff_macro(p, "RE", NULL); - } else if (i == *indent + 1) { - roff_macro(p, "RS", "4", NULL); - } else if (i != *indent && ch == '\t') { - parser_fatal(p, "(De)indented by an amount greater than 1"); + if (write) { + if (i == *indent - 1) { + roff_macro(p, "RE", NULL); + } else if (i == *indent + 1) { + roff_macro(p, "RS", "4", NULL); + } else if (i != *indent && ch == '\t') { + parser_fatal(p, "(De)indented by an amount greater than 1"); + } } *indent = i; return i; @@ -176,7 +178,7 @@ } roff_macro(p, "IP", "\\(bu", "4", NULL); parse_text(p); do { - parse_indent(p, indent); + parse_indent(p, indent, true); if ((ch = parser_getch(p)) == UTF8_INVALID) { break; } @@ -199,11 +201,67 @@ } } while (ch != UTF8_INVALID); } +static void parse_literal(struct parser *p, int *indent) { + uint32_t ch; + if ((ch = parser_getch(p)) != '`' || + (ch = parser_getch(p)) != '`' || + (ch = parser_getch(p)) != '\n') { + parser_fatal(p, "Expected ``` and a newline to begin literal block"); + } + int stops = 0; + roff_macro(p, "nf", NULL); + roff_macro(p, "RS", "4", NULL); + do { + int _indent = *indent; + parse_indent(p, &_indent, false); + if (_indent < *indent) { + parser_fatal(p, "Cannot deindent in literal block"); + } + while (_indent > *indent) { + --_indent; + fprintf(p->output, "\t"); + } + if ((ch = parser_getch(p)) == UTF8_INVALID) { + break; + } + if (ch == '`') { + if (++stops == 3) { + if ((ch = parser_getch(p)) != '\n') { + parser_fatal(p, "Expected literal block to end with newline"); + } + roff_macro(p, "fi", NULL); + roff_macro(p, "RE", NULL); + return; + } + } else { + stops = 0; + switch (ch) { + case '.': + fprintf(p->output, "\\&."); + break; + case '\\': + ch = parser_getch(p); + if (ch == UTF8_INVALID) { + parser_fatal(p, "Unexpected EOF"); + } else if (ch == '\\') { + fprintf(p->output, "\\\\"); + } else { + utf8_fputch(p->output, ch); + } + break; + default: + utf8_fputch(p->output, ch); + break; + } + } + } while (ch != UTF8_INVALID); +} + static void parse_document(struct parser *p) { uint32_t ch; int indent = 0; do { - parse_indent(p, &indent); + parse_indent(p, &indent, true); if ((ch = parser_getch(p)) == UTF8_INVALID) { break; } @@ -218,6 +276,9 @@ parse_heading(p); break; case '-': parse_list(p, &indent); + break; + case '`': + parse_literal(p, &indent); break; case ' ': parser_fatal(p, "Tabs are required for indentation"); -- 2.48.1