Handle indent/deindent

master
Drew DeVault 7 years ago
parent 9f74b6a0bf
commit 35028f262a
  1. 3
      include/util.h
  2. 48
      src/main.c
  3. 9
      src/util.c

@ -7,10 +7,13 @@
struct parser {
FILE *input, *output;
int line, col;
int qhead;
uint32_t queue[32];
};
void parser_fatal(struct parser *parser, const char *err);
uint32_t parser_getch(struct parser *parser);
void parser_pushch(struct parser *parser, uint32_t ch);
int roff_macro(struct parser *p, char *cmd, ...);
#endif

@ -62,11 +62,19 @@ static void parse_preamble(struct parser *p) {
static void parse_text(struct parser *p) {
uint32_t ch;
int i = 0;
while ((ch = parser_getch(p)) != UTF8_INVALID) {
switch (ch) {
case '\\':
fprintf(p->output, "\\\\");
break;
case '.':
if (!i) {
// Escape . if it's the first character
fprintf(p->output, "\\&.");
break;
}
/* fallthrough */
default:
utf8_fputch(p->output, ch);
break;
@ -74,6 +82,7 @@ static void parse_text(struct parser *p) {
if (ch == '\n') {
break;
}
++i;
}
}
@ -108,9 +117,35 @@ static void parse_heading(struct parser *p) {
}
}
static int parse_indent(struct parser *p) {
int i = 0;
uint32_t ch;
while ((ch = parser_getch(p)) == '\t') {
++i;
}
parser_pushch(p, ch);
return i;
}
static void parse_document(struct parser *p) {
uint32_t ch;
while ((ch = parser_getch(p)) != UTF8_INVALID) {
int indent = 0;
do {
int i = parse_indent(p);
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;
ch = parser_getch(p);
if (ch == UTF8_INVALID) {
break;
}
switch (ch) {
case '#':
parse_heading(p);
@ -118,16 +153,15 @@ static void parse_document(struct parser *p) {
case '\n':
roff_macro(p, "P", NULL);
break;
case ' ':
parser_fatal(p, "Tabs are required for indentation");
break;
default:
if (ch == '.') {
fprintf(p->output, "\\&.");
} else {
utf8_fputch(p->output, ch);
}
parser_pushch(p, ch);
parse_text(p);
break;
}
}
} while (ch != UTF8_INVALID);
}
static void output_scdoc_preamble(struct parser *p) {

@ -14,6 +14,9 @@ void parser_fatal(struct parser *parser, const char *err) {
}
uint32_t parser_getch(struct parser *parser) {
if (parser->qhead) {
return parser->queue[--parser->qhead];
}
uint32_t ch = utf8_fgetch(parser->input);
if (ch == '\n') {
parser->col = 0;
@ -24,6 +27,12 @@ uint32_t parser_getch(struct parser *parser) {
return ch;
}
void parser_pushch(struct parser *parser, uint32_t ch) {
if (ch != UTF8_INVALID) {
parser->queue[parser->qhead++] = ch;
}
}
int roff_macro(struct parser *p, char *cmd, ...) {
FILE *f = p->output;
int l = fprintf(f, ".%s", cmd);

Loading…
Cancel
Save