diff options
author | Akim Demaille <akim.demaille@gmail.com> | 2020-03-07 12:59:09 +0100 |
---|---|---|
committer | Akim Demaille <akim.demaille@gmail.com> | 2020-03-08 08:10:11 +0100 |
commit | b6386034773829b10c44ff93ce0a492980684c64 (patch) | |
tree | e2c868c81bba7d4bcf21ce2d06a34a5da1896e9d /src/location.c | |
parent | e21ff47f5d0b64da693a47b7dd200a1a44a5bbeb (diff) | |
download | bison-b6386034773829b10c44ff93ce0a492980684c64.tar.gz |
diagnostics: beware of zero-width characters
Currenly we rely on (visual) width of the characters to decide where
to open and close the styling of the quoted lines. This breaks when
we deal with zero-width characters: we cannot just rely on (visual)
columns, we need to know whether we are before, inside, or after the
highlighted portion.
* src/location.c (location_caret): col_end: no longer add 1, "regular"
characters have a width of 1, only 0-width characters have 0-width.
opened: replace with 'state', a three-valued enum.
Don't reopen the style if we already did.
* tests/diagnostics.at (Zero-width characters): New.
Diffstat (limited to 'src/location.c')
-rw-r--r-- | src/location.c | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/src/location.c b/src/location.c index dbcd67ec..9f929c00 100644 --- a/src/location.c +++ b/src/location.c @@ -421,12 +421,14 @@ location_caret (location loc, const char *style, FILE *out) { /* The last column to highlight. Only the first line of multiline locations are quoted, in which case the ending - column is the end of line. Single point locations (with - equal boundaries) denote the character that they - follow. */ - int col_end + column is the end of line. + + We used to work with byte offsets, and that was much + easier. However, we went back to using (visual) columns to + support truncating of long lines. */ + const int col_end = loc.start.line == loc.end.line - ? loc.end.column + (loc.start.column == loc.end.column) + ? loc.end.column : caret_info.line_len; /* Quote the file (at most the first line in the case of multiline locations). */ @@ -436,24 +438,28 @@ location_caret (location loc, const char *style, FILE *out) expected (maybe the file was changed since the scanner ran), we might reach the end before we actually saw the opening column. */ - bool opened = false; + enum { before, inside, after } state = before; while (!mb_iseof (c) && !mb_iseq (c, '\n')) { - if (caret_info.pos.column == loc.start.column) + // We might have already opened (and even closed!) the + // style and yet have the equality of the columns if we + // just saw zero-width characters. + if (state == before + && caret_info.pos.column == loc.start.column) { begin_use_class (style, out); - opened = true; + state = inside; } if (skip < caret_info.pos.column) mb_putc (c, out); boundary_compute (&caret_info.pos, mb_ptr (c), mb_len (c)); caret_getc (c); - if (opened + if (state == inside && (caret_info.pos.column == col_end || width < caret_info.pos.column - skip)) { end_use_class (style, out); - opened = false; + state = after; } if (width < caret_info.pos.column - skip) { @@ -461,11 +467,11 @@ location_caret (location loc, const char *style, FILE *out) break; } } - // The line is shorter than expected. - if (opened) + if (state == inside) { + // The line is shorter than expected. end_use_class (style, out); - opened = false; + state = after; } putc ('\n', out); } |