ww source: align UTF-8 BOM placement
This commit is contained in:
@@ -7,6 +7,15 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
static int
|
||||
bomat(const char *src, u64 len, u64 pos)
|
||||
{
|
||||
return pos <= len && len - pos >= 3
|
||||
&& (unsigned char)src[pos] == 0xef
|
||||
&& (unsigned char)src[pos + 1] == 0xbb
|
||||
&& (unsigned char)src[pos + 2] == 0xbf;
|
||||
}
|
||||
|
||||
void
|
||||
lexinit(Lex *l, Arena *a, const char *file, const char *src, u64 len)
|
||||
{
|
||||
@@ -17,6 +26,12 @@ lexinit(Lex *l, Arena *a, const char *file, const char *src, u64 len)
|
||||
l->line = 1;
|
||||
l->col = 1;
|
||||
l->a = a;
|
||||
/* Go 1.26.5 syntax.source.nextch ignores U+FEFF only at the first
|
||||
* source position but counts its three bytes for the next column. */
|
||||
if (bomat(src, len, 0)) {
|
||||
l->pos = 3;
|
||||
l->col = 4;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -25,6 +40,8 @@ lpeek(Lex *l, u64 ahead)
|
||||
u64 p = l->pos + ahead;
|
||||
if (p >= l->srclen)
|
||||
return -1;
|
||||
if (bomat(l->src, l->srclen, p))
|
||||
return 0xfeff;
|
||||
return (unsigned char)l->src[p];
|
||||
}
|
||||
|
||||
@@ -33,6 +50,14 @@ lget(Lex *l)
|
||||
{
|
||||
if (l->pos >= l->srclen)
|
||||
return -1;
|
||||
if (bomat(l->src, l->srclen, l->pos)) {
|
||||
Pos p = { l->file, l->line, l->col };
|
||||
l->pos += 3;
|
||||
l->col += 3;
|
||||
errorf(p, "invalid BOM in the middle of the file");
|
||||
l->errs++;
|
||||
return 0xfeff;
|
||||
}
|
||||
int c = (unsigned char)l->src[l->pos++];
|
||||
if (c == '\n') {
|
||||
l->line++;
|
||||
@@ -529,6 +554,11 @@ lexnext(Lex *l)
|
||||
return t;
|
||||
}
|
||||
int c = lpeek(l, 0);
|
||||
if (c == 0xfeff) {
|
||||
lget(l);
|
||||
Tok t = (Tok){ TK_ERR, start, "", 0, {0}, TK_NONE };
|
||||
return t;
|
||||
}
|
||||
|
||||
if (isidstart(c))
|
||||
return lexident(l, start);
|
||||
|
||||
@@ -4740,7 +4740,18 @@ sep_emit_body(FILE *out, const char *path, const char *modpath)
|
||||
} else if (fputs("//ww:module-reset\n", out) == EOF) {
|
||||
bad = 1;
|
||||
}
|
||||
if (fwrite(buf, 1, (size_t)len, out) != (size_t)len
|
||||
/* Each physical source owns its own first-codepoint position. The
|
||||
* compiler sees one synthetic aggregate, so replace the optional UTF-8
|
||||
* BOM with position-preserving whitespace rather than turning a later
|
||||
* source's marker into a mid-unit BOM. */
|
||||
u64 off = len >= 3
|
||||
&& (unsigned char)buf[0] == 0xef
|
||||
&& (unsigned char)buf[1] == 0xbb
|
||||
&& (unsigned char)buf[2] == 0xbf ? 3 : 0;
|
||||
if (off != 0 && fwrite(" ", 1, 3, out) != 3)
|
||||
bad = 1;
|
||||
if (fwrite(buf + off, 1, (size_t)(len - off), out)
|
||||
!= (size_t)(len - off)
|
||||
|| fputc('\n', out) == EOF)
|
||||
bad = 1;
|
||||
free(buf);
|
||||
|
||||
Reference in New Issue
Block a user