commit 5f44aae0f77cb9c8a0be83954cd67c0a650ad36c
parent 688923fabc4b09aff9f92f5b0c62d96fff7aced7
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 10 Dec 2017 01:10:04 -0500
Implement literal sections
Diffstat:
M | src/main.c | | | 79 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- |
1 file changed, 70 insertions(+), 9 deletions(-)
diff --git a/src/main.c b/src/main.c
@@ -150,19 +150,21 @@ static void parse_heading(struct parser *p) {
}
}
-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 @@ static void parse_list(struct parser *p, int *indent) {
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 @@ static void parse_list(struct parser *p, int *indent) {
} 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;
}
@@ -219,6 +277,9 @@ static void parse_document(struct parser *p) {
case '-':
parse_list(p, &indent);
break;
+ case '`':
+ parse_literal(p, &indent);
+ break;
case ' ':
parser_fatal(p, "Tabs are required for indentation");
break;