A newline inside a string is still a newline

readToken consumed a string literal character by character and counted
none of the newlines in it, so every line number after a multi-line
string was short by one - and by one more for each one after that.

cosmos.asm has seven such strings spanning thirteen lines, so by the end
of the file the assembler was reporting labels thirteen lines early.
That was never only a cosmetic problem: the same counter is what every
error message names, so an error anywhere after the help text was
pointing at somebody else's code, thirteen lines away, with no sign that
it was doing so.

Found because the symbol table started publishing line numbers, which
made a wrong one something you could look at. Verified against all 797
of cosmos.asm's labels, every one of which now names the line it is
actually on. The check that keeps it that way comes with the next
commit, which is what gives it something to check.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
Anachronaut
2026-09-05 10:51:36 -04:00
co-authored by Claude Opus 5
parent 3527812c41
commit ca6c8ca6ad
+9
View File
@@ -309,6 +309,15 @@ int readToken(intermediateElement *currentElement, FILE *file, int *lineNumber)
// Step 3: Handle string literals
if (c == '"') {
while ((c = fgetc(file)) != EOF && c != '"') {
// A STRING MAY HAVE NEWLINES IN IT, and they are as real as any others. Not
// counting them is why every line number after one was short: cosmos.asm has
// thirteen of them and its last label was reported thirteen lines early, which
// makes an error message point at somebody else's code. Counted here, where
// the character is consumed, rather than by scanning the token afterwards -
// the same newline must not be counted twice if this loop ever grows a way out.
if (c == '\n') {
(*lineNumber)++;
}
if (i < (int)(sizeof(buffer) - 1)) {
buffer[i++] = c;
} else {