From 25832ef5fcd5509a8b91accbaa8dabdefce595a6 Mon Sep 17 00:00:00 2001 From: acqn Date: Fri, 13 Oct 2023 16:32:06 +0800 Subject: [PATCH] Fixed timing of #pragma charmap. Now it is immediately applied and affects almost all characters and string literals after it. Exceptions: - String literals as the message of a static assertion or inline assembler code (only the required one, not any optional formatted arguments) in an asm() expression are not translated with either #pragma charmap or target presets. - String literals used for preprocessor directives or as the result of stringized macro arguments are never translated. --- src/cc65/asmstmt.c | 9 +++++++ src/cc65/expr.c | 2 -- src/cc65/initdata.c | 3 --- src/cc65/pragma.c | 6 +++++ src/cc65/scanner.c | 21 ++++++++++++---- src/cc65/scanner.h | 8 +++--- src/cc65/staticassert.c | 8 +++++- test/val/bug2151.c | 54 ++++++++++++++++++++++++++++++++++++++--- 8 files changed, 94 insertions(+), 17 deletions(-) diff --git a/src/cc65/asmstmt.c b/src/cc65/asmstmt.c index d182140fd..6cb6f2ef7 100644 --- a/src/cc65/asmstmt.c +++ b/src/cc65/asmstmt.c @@ -417,6 +417,9 @@ void AsmStatement (void) ** a string literal in parenthesis. */ { + /* Prevent from translating the inline code string literal in asm */ + NoCharMap = 1; + /* Skip the ASM */ NextToken (); @@ -431,9 +434,15 @@ void AsmStatement (void) /* Need left parenthesis */ if (!ConsumeLParen ()) { + NoCharMap = 0; return; } + /* We have got the inline code string untranslated, now reenable string + ** literal translation for string arguments (if any). + */ + NoCharMap = 0; + /* String literal */ if (CurTok.Tok != TOK_SCONST) { diff --git a/src/cc65/expr.c b/src/cc65/expr.c index f6b069f3f..8b0824c31 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -1336,8 +1336,6 @@ static void Primary (ExprDesc* E) /* String literal */ if ((Flags & E_EVAL_UNEVAL) != E_EVAL_UNEVAL) { E->V.LVal = UseLiteral (CurTok.SVal); - /* Translate into target charset */ - TranslateLiteral (E->V.LVal); } else { E->V.LVal = CurTok.SVal; } diff --git a/src/cc65/initdata.c b/src/cc65/initdata.c index f576c0255..5702d57c1 100644 --- a/src/cc65/initdata.c +++ b/src/cc65/initdata.c @@ -245,9 +245,6 @@ static void DefineBitFieldData (StructInitData* SI) static void DefineStrData (Literal* Lit, unsigned Count) { - /* Translate into target charset */ - TranslateLiteral (Lit); - /* Output the data */ g_defbytes (GetLiteralStr (Lit), Count); } diff --git a/src/cc65/pragma.c b/src/cc65/pragma.c index 21d426a26..db306040d 100644 --- a/src/cc65/pragma.c +++ b/src/cc65/pragma.c @@ -1096,8 +1096,12 @@ void ConsumePragma (void) /* Skip the _Pragma token */ NextToken (); + /* Prevent from translating string literals in _Pragma */ + ++InPragmaParser; + /* We expect an opening paren */ if (!ConsumeLParen ()) { + --InPragmaParser; return; } @@ -1115,6 +1119,8 @@ void ConsumePragma (void) ParsePragmaString (); } + --InPragmaParser; + /* Closing paren needed */ ConsumeRParen (); } diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index e9ef34173..409e778ab 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -70,10 +70,12 @@ -static Token SavedTok; /* Saved token */ -Token CurTok; /* The current token */ -Token NextTok; /* The next token */ -int PPParserRunning; /* Is tokenizer used by the preprocessor */ +static Token SavedTok; /* Saved token */ +Token CurTok; /* The current token */ +Token NextTok; /* The next token */ +int PPParserRunning; /* Is tokenizer used by the preprocessor */ +int NoCharMap; /* Disable literal translation */ +unsigned InPragmaParser; /* Depth of pragma parser calling */ @@ -455,7 +457,7 @@ static void CharConst (void) } /* Translate into target charset */ - NextTok.IVal = SignExtendChar (TgtTranslateChar (C)); + NextTok.IVal = SignExtendChar (C); /* Character constants have type int */ NextTok.Type = type_int; @@ -798,6 +800,15 @@ static void GetNextInputToken (void) { ident token; + if (!NoCharMap && !InPragmaParser) { + /* Translate string and character literals into target charset */ + if (NextTok.Tok == TOK_SCONST || NextTok.Tok == TOK_WCSCONST) { + TranslateLiteral (NextTok.SVal); + } else if (NextTok.Tok == TOK_CCONST || NextTok.Tok == TOK_WCCONST) { + NextTok.IVal = SignExtendChar (TgtTranslateChar (NextTok.IVal)); + } + } + /* Current token is the lookahead token */ if (CurTok.LI) { ReleaseLineInfo (CurTok.LI); diff --git a/src/cc65/scanner.h b/src/cc65/scanner.h index cff2b0347..e6b788660 100644 --- a/src/cc65/scanner.h +++ b/src/cc65/scanner.h @@ -219,9 +219,11 @@ struct Token { const Type* Type; /* Type if integer or float constant */ }; -extern Token CurTok; /* The current token */ -extern Token NextTok; /* The next token */ -extern int PPParserRunning; /* Is tokenizer used by the preprocessor */ +extern Token CurTok; /* The current token */ +extern Token NextTok; /* The next token */ +extern int PPParserRunning; /* Is tokenizer used by the preprocessor */ +extern int NoCharMap; /* Disable literal translation */ +extern unsigned InPragmaParser; /* Depth of pragma parser calling */ diff --git a/src/cc65/staticassert.c b/src/cc65/staticassert.c index 1bf8dd4c5..abb2c57ca 100644 --- a/src/cc65/staticassert.c +++ b/src/cc65/staticassert.c @@ -72,9 +72,15 @@ void ParseStaticAssert () ** support the C2X syntax with only an expression. */ if (CurTok.Tok == TOK_COMMA) { - /* Skip the comma. */ + /* Prevent from translating the message string literal */ + NoCharMap = 1; + + /* Skip the comma and get the next token */ NextToken (); + /* Reenable string literal translation */ + NoCharMap = 0; + /* String literal */ if (CurTok.Tok != TOK_SCONST) { Error ("String literal expected for static_assert message"); diff --git a/test/val/bug2151.c b/test/val/bug2151.c index 905eeac39..25f145506 100644 --- a/test/val/bug2151.c +++ b/test/val/bug2151.c @@ -1,9 +1,39 @@ /* Bug #2151 - #pragma causes errors when used within functions */ +#include +#include + +#pragma charmap(0x61, 0x61) +_Static_assert('A'== +#pragma charmap(0x61, 0x41) +'a' +#pragma charmap(0x61, 0x42) +, +#pragma charmap(0x61, 0x61) +"charmap failed"); + +char str[] = +"a" +#pragma charmap(0x61, 0x42) +"a" +#pragma charmap(0x61, 0x43) +"a" +#pragma charmap(0x61, 0x61) +; + +unsigned failures; + #pragma bss-name("BSS1") int #pragma code-name("CODE_WUT") -main _Pragma("message(\"_Pragma note\")") +main _Pragma +#pragma charmap(0x61, 0x32) +( +"message(\"_Pragma string" +/* Concatenated string literals in _Pragma is a cc65 extension */ +" unaffected by charmap\")" +) +#pragma charmap(0x61, 0x61) ( void _Pragma _Pragma ( @@ -20,9 +50,27 @@ _Pragma _Pragma ( #pragma bss-name("BSS2") static #pragma zpsym ("y") - int x; // TODO: currently in "BSS", but supposed to be in "BSS2"? + int x; // TODO: currently in "BSS", but supposed to be in "BSS2"? x = 0; - return x + y; + + if (memcmp(str, "aBC", 3)) + { + ++failures; + printf("%3s\n", str); + } + + if (x + y != 0) + { + ++failures; + printf("%d\n", x + y); + } + + if (failures != 0) + { + printf("faiures: %d\n", failures); + } + + return failures; #pragma bss-name("BSS") }