~sircmpwn/public-inbox

General catch-all for patches, questions, and discussions for sircmpwn's projects that don't have their own mailing list.

When posting patches to this list, please edit the [PATCH] line to include the specific project you're contributing to, e.g.

[PATCH scdoc v2] Add thing to stuff
3 2

[PATCH] fix bug preventing indented literal blocks

Zandr Martin
Details
Message ID
<20190812132016.83176-1-git@zandr.me>
DKIM signature
pass
Download raw message
Patch: +15 -8
This commit fixes a bug in parsing indented literal blocks. For example:

test(8)

	```
	This is a block
	```

Prior to this commit, this would fail, but with an unexpected error
message: "Error at 4:3: Cannot deindent in literal block". The
indentation was being parsed at every character, so the parser saw the
`T`, then parsed indentation again. The indentation was 0 (since there
were no tab characters between the `T` and the `h`), but the block
started with an indentation level of 1. 0 < 1, so this would be
considered a dedent, which is not allowed.

This commit introduces a new local variable, `should_parse_indent`,
which controls whether the parser tries to parse indentation or not; now
indentation is only parsed when the last character was a newline. From
my testing this seems to fix the issue - indented literal blocks are now
allowed.
---
 src/main.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/src/main.c b/src/main.c
index 72b7eaf..89ca825 100644
--- a/src/main.c
+++ b/src/main.c
@@ -374,15 +374,19 @@ static void parse_literal(struct parser *p, int *indent) {
 	int stops = 0;
 	roff_macro(p, "nf", NULL);
 	fprintf(p->output, ".RS 4\n");
+	bool should_parse_indent = true;
 	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 (should_parse_indent) {
+			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");
+			}
+			should_parse_indent = false;
 		}
 		if ((ch = parser_getch(p)) == UTF8_INVALID) {
 			break;
@@ -415,6 +419,9 @@ static void parse_literal(struct parser *p, int *indent) {
 					utf8_fputch(p->output, ch);
 				}
 				break;
+			case '\n':
+				should_parse_indent = true;
+				/* fallthrough */
 			default:
 				utf8_fputch(p->output, ch);
 				break;
--
2.22.0
Details
Message ID
<BW84OBRJPAGD.DMB5O59SF69I@koishi>
In-Reply-To
<20190812132016.83176-1-git@zandr.me> (view parent)
DKIM signature
pass
Download raw message
Can you add a test case for this?

On Mon Aug 12, 2019 at 9:20 AM Zandr Martin wrote:
> +	bool should_parse_indent = true;

Would prefer to call this "parse_indent" for brevity's sake.
Zandr Martin
Details
Message ID
<20190813112956.GA974@megalith.local>
In-Reply-To
<BW84OBRJPAGD.DMB5O59SF69I@koishi> (view parent)
DKIM signature
pass
Download raw message
On Mon, Aug 12, 2019 at 09:58:02PM EDT, Drew DeVault wrote:
>Can you add a test case for this?

Yep, will do.

>> +	bool should_parse_indent = true;
>
>Would prefer to call this "parse_indent" for brevity's sake.

That was my first thought too, but `parse_indent` is already the name of 
a function so that won't work. I'm open to suggestions. Does 
`check_indent` work for you?
Details
Message ID
<BW8GVBMGUOFJ.2UYF261CQFPMK@koishi>
In-Reply-To
<20190813112956.GA974@megalith.local> (view parent)
DKIM signature
pass
Download raw message
On Tue Aug 13, 2019 at 7:29 AM Zandr Martin wrote:
> That was my first thought too, but `parse_indent` is already the name of 
> a function so that won't work. I'm open to suggestions. Does 
> `check_indent` work for you?

+1