diff --git a/src/link/output.cpp b/src/link/output.cpp index e584ce916..f7760ce73 100644 --- a/src/link/output.cpp +++ b/src/link/output.cpp @@ -266,15 +266,15 @@ static bool isLegalForSymName(char c) { || c == '@' || c == '#' || c == '$' || c == '.'; } -// Prints a symbol's name to `symFile`, assuming that the first character is legal. +// Prints a symbol's name to a file, assuming that the first character is legal. // Illegal characters are UTF-8-decoded (errors are replaced by U+FFFD) and emitted as `\u`/`\U`. -static void printSymName(char const *name) { - for (char const *ptr = name; *ptr != '\0';) { +static void printSymName(std::string const &name, FILE *file) { + for (char const *ptr = name.c_str(); *ptr != '\0';) { char c = *ptr; if (isLegalForSymName(c)) { // Output legal ASCII characters as-is - putc(c, symFile); + putc(c, file); ++ptr; } else { // Output illegal characters using Unicode escapes @@ -295,7 +295,7 @@ static void printSymName(char const *name) { ++ptr; } while (state != 0); - fprintf(symFile, codepoint <= 0xFFFF ? "\\u%04" PRIx32 : "\\U%08" PRIx32, codepoint); + fprintf(file, codepoint <= 0xFFFF ? "\\u%04" PRIx32 : "\\U%08" PRIx32, codepoint); } } } @@ -376,7 +376,7 @@ static void writeSymBank(SortedSections const &bankSections, SectionType type, u for (SortedSymbol &sym : symList) { fprintf(symFile, "%02" PRIx32 ":%04" PRIx16 " ", symBank, sym.addr); - printSymName(sym.sym->name.c_str()); + printSymName(sym.sym->name, symFile); putc('\n', symFile); } } @@ -396,6 +396,31 @@ static void writeEmptySpace(uint16_t begin, uint16_t end) { } } +// Prints a section's name to a file. +static void printSectionName(std::string const &name, FILE *file) { + for (char c : name) { + // Escape characters that need escaping + switch (c) { + case '\n': + fputs("\\n", file); + break; + case '\r': + fputs("\\r", file); + break; + case '\t': + fputs("\\t", file); + break; + case '\\': + case '"': + putc('\\', file); + [[fallthrough]]; + default: + putc(c, file); + break; + } + } +} + /* * Write a bank's contents to the map file */ @@ -427,35 +452,22 @@ static void writeMapBank(SortedSections const §List, SectionType type, uint3 prevEndAddr = sect->org + sect->size; + fprintf(mapFile, "\tSECTION: $%04" PRIx16, sect->org); if (sect->size != 0) - fprintf( - mapFile, - "\tSECTION: $%04" PRIx16 "-$%04x ($%04" PRIx16 " byte%s) [\"%s\"]\n", - sect->org, - prevEndAddr - 1, - sect->size, - sect->size == 1 ? "" : "s", - sect->name.c_str() - ); - else - fprintf( - mapFile, - "\tSECTION: $%04" PRIx16 " (0 bytes) [\"%s\"]\n", - sect->org, - sect->name.c_str() - ); + fprintf(mapFile, "-$%04x", prevEndAddr - 1); + fprintf(mapFile, " ($%04" PRIx16 " byte%s) [\"", sect->size, sect->size == 1 ? "" : "s"); + printSectionName(sect->name, mapFile); + fputs("\"]\n", mapFile); if (!noSymInMap) { // Also print symbols in the following "pieces" for (uint16_t org = sect->org; sect; sect = sect->nextu.get()) { - for (Symbol *sym : sect->symbols) + for (Symbol *sym : sect->symbols) { // Space matches "\tSECTION: $xxxx ..." - fprintf( - mapFile, - "\t $%04" PRIx32 " = %s\n", - sym->label().offset + org, - sym->name.c_str() - ); + fprintf(mapFile, "\t $%04" PRIx32 " = ", sym->label().offset + org); + printSymName(sym->name, mapFile); + putc('\n', mapFile); + } if (sect->nextu) { // Announce the following "piece" @@ -579,7 +591,9 @@ static void writeSym() { for (Symbol *sym : constants) { int32_t val = sym->data.get(); int width = val < 0x100 ? 2 : val < 0x10000 ? 4 : 8; - fprintf(symFile, "%0*" PRIx32 " %s\n", width, val, sym->name.c_str()); + fprintf(symFile, "%0*" PRIx32 " ", width, val); + printSymName(sym->name, symFile); + putc('\n', symFile); } } diff --git a/test/link/map-file/a.asm b/test/link/map-file/a.asm index dd9f676ea..9f19a1746 100644 --- a/test/link/map-file/a.asm +++ b/test/link/map-file/a.asm @@ -25,3 +25,5 @@ wLabel1:: ds 6 SECTION "hram", HRAM hLabel:: ds 7 .local:: + +SECTION "\n\r\t\"\\", ROM0[1] diff --git a/test/link/map-file/ref.out.map b/test/link/map-file/ref.out.map index 5ad9797af..b12a83481 100644 --- a/test/link/map-file/ref.out.map +++ b/test/link/map-file/ref.out.map @@ -10,6 +10,7 @@ ROM0 bank #0: SECTION: $0000-$0000 ($0001 byte) ["rom0"] $0000 = Label0 $0001 = Label0.local + SECTION: $0001 ($0000 bytes) ["\n\r\t\"\\"] EMPTY: $0001-$3fff ($3fff bytes) TOTAL EMPTY: $3fff bytes