A string that spells a directive is a string, not a directive

The quotes are gone by the time a token is classified, so checkIfKeyword's
test of token[0] == '#' matched the STRING "#Program" sitting in a program's
Data Segment. It was read as the directive: the segment silently changed in
the middle of the data, the string's nine bytes were charged to the Program
cursor instead of the Data one, and every label defined after it came out
nine bytes wrong - in a file that still had a valid header, a plausible
length, and nothing to say about any of it. The only symptom was a program
that jumped into the middle of an instruction.

This is the FOURTH of the family. A string spelling a mnemonic assembled as
that instruction; a string beginning with a zero was rejected as a malformed
literal; a string in the Program Segment was discarded in silence. The
instruction check and the literal check both carry a "not a STRING" guard
already. This one did not, so it has one now, and it lives inside
checkIfKeyword rather than at the call site so it cannot be left off again.

Nothing had ever triggered it, because nothing had ever needed a directive's
name as data. An assembler written FOR this machine necessarily does: it has
to compare tokens against "#Program" and "#Data". It was found by building
one and watching it fault on its second instruction.

Test stringKeyword puts every directive name in a program's data and prints
a label defined after them. Verified that it bites: without the fix the
assembler refuses the file outright.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
Anachronaut
2026-08-20 22:12:47 -04:00
co-authored by Claude Opus 5
parent ca243895ca
commit a131a90c67
4 changed files with 70 additions and 0 deletions
+13
View File
@@ -44,6 +44,19 @@ void toUppercase(char *str) {
}
int checkIfKeyword(intermediateElement *currentElement) {
// A string is never a keyword, however it is spelled. The quotes are gone by the time
// a token is looked at, so a program with "#Program" in its data - which is exactly
// what an assembler written for this machine needs, to compare tokens against - had
// the string read as the directive. The segment silently changed in the middle of the
// Data Segment, the string's nine bytes were charged to the Program cursor, and every
// label after it was nine bytes out while the file itself still looked well formed.
//
// This is the fourth of this family: the instruction check and the literal check both
// carry the same guard, for the same reason. It lives inside this one rather than at
// the call site so that it cannot be left off again.
if (currentElement->type == STRING) {
return 0;
}
if (currentElement->token[0] == '#') {
if (debug) printf("Token: %s is a keyword.\n", currentElement->token);
currentElement->type = KEYWORD;