Say that an option's file is one the assembler writes, and check we said it

-S was added without a row in the Assembler Manual, and the usage it
printed listed a bare "-S <file>" with no long name and no statement of
what the file is for. That is not merely incomplete, it is misleading:
"-S <file>" reads just as naturally as "dump the symbols of <file>", and
asking for it that way hands the source to -S, leaves nothing positional
behind it, and is answered with "No source file specified" on a command
line that plainly names a source. The error described the hole the
mistake left and hid the mistake.

So the usage now prints the long names, says outright that every <file>
is a path it writes and the source is the last argument on its own, and
ends with a whole example command. When the source is missing and a
file-taking option was given, the error says which options take a path
to write. The manual gains the -S row it never had, a warning in the
same words, and a sentence on what a symbol dump is for.

Documenting it twice is how it went wrong once, so docs.sh now settles
both against getopt's own option table: every option the assembler takes
has a row in the manual and a line in its own usage. Verified with
break.sh against the manual row and the usage line separately.

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 09:40:21 -04:00
co-authored by Claude Opus 5
parent cdee9acfae
commit 7a55cfe151
3 changed files with 65 additions and 5 deletions
+26 -5
View File
@@ -95,15 +95,28 @@ void assemblerCleanup(intermediateElement *intermediateArray, int arraySize, cha
free(outputFileName);
}
// EVERY OPTION HERE NAMES A FILE THE ASSEMBLER WRITES, and the source is the bare argument
// at the end. A list of bare flags does not say that: "-S <file>" reads just as naturally as
// "dump the symbols of <file>", and asking for it that way hands the source to -S, leaves
// nothing positional behind it, and gets answered with "No source file specified" - which
// describes the symptom and hides the cause. So the long names are printed, every line says
// where the file is written, and an example shows a whole command rather than leaving one to
// be assembled out of the parts.
void printUsage(const char *programName) {
printf("Usage: %s [OPTIONS] <sourcefile>\n", programName);
printf("\n");
printf("Assembles one source file. The source is the last argument, on its own; every\n");
printf("<file> below is a path the assembler writes, and every <dir> one it searches.\n");
printf("\n");
printf("Options:\n");
printf(" -o <file> Write the output to this path instead of alongside the source.\n");
printf(" -I <dir> Look in this directory for included files. May be given more than once.\n");
printf(" -M <file> Write the source files this output depends on, as a make rule.\n");
printf(" -S <file> Write every label and the address it was given, in address order.\n");
printf(" -h, --help Display this help message.\n");
printf(" -o, --output <file> Write the assembled output here, instead of alongside the source.\n");
printf(" -I, --include <dir> Search this directory for included files. May be given more than once.\n");
printf(" -M, --depend <file> Write a make rule here, naming every source that went into the output.\n");
printf(" -S, --symbols <file> Write every label here with the address it was given, in address order.\n");
printf(" -h, --help Display this help message.\n");
printf("\n");
printf("Example:\n");
printf(" %s -I Libraries -S game.sym -o game.sbx game.asm\n", programName);
}
// Writes a make rule naming every source file that went into the output, so that a
@@ -207,6 +220,14 @@ int main(int argc, char *argv[]) {
if (optind >= argc) {
fprintf(stderr, RED "Error: No source file specified.\n" RESET);
// The commonest way to get here is giving the source to an option that wanted a
// path to write, which consumes it and leaves nothing positional. Saying so is the
// difference between an error that names the mistake and one that names the hole
// the mistake left behind.
if (outputFileName || dependencyFileName || symbolFileName) {
fprintf(stderr, " -o, -M and -S each name a file to WRITE, not one to read.\n"
" The source file is the last argument, on its own.\n");
}
printUsage(argv[0]);
return 1;
}