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.
This commit is contained in:
acqn
2023-10-13 16:32:06 +08:00
parent c6ead99b00
commit 25832ef5fc
8 changed files with 94 additions and 17 deletions

View File

@@ -417,6 +417,9 @@ void AsmStatement (void)
** a string literal in parenthesis. ** a string literal in parenthesis.
*/ */
{ {
/* Prevent from translating the inline code string literal in asm */
NoCharMap = 1;
/* Skip the ASM */ /* Skip the ASM */
NextToken (); NextToken ();
@@ -431,9 +434,15 @@ void AsmStatement (void)
/* Need left parenthesis */ /* Need left parenthesis */
if (!ConsumeLParen ()) { if (!ConsumeLParen ()) {
NoCharMap = 0;
return; return;
} }
/* We have got the inline code string untranslated, now reenable string
** literal translation for string arguments (if any).
*/
NoCharMap = 0;
/* String literal */ /* String literal */
if (CurTok.Tok != TOK_SCONST) { if (CurTok.Tok != TOK_SCONST) {

View File

@@ -1336,8 +1336,6 @@ static void Primary (ExprDesc* E)
/* String literal */ /* String literal */
if ((Flags & E_EVAL_UNEVAL) != E_EVAL_UNEVAL) { if ((Flags & E_EVAL_UNEVAL) != E_EVAL_UNEVAL) {
E->V.LVal = UseLiteral (CurTok.SVal); E->V.LVal = UseLiteral (CurTok.SVal);
/* Translate into target charset */
TranslateLiteral (E->V.LVal);
} else { } else {
E->V.LVal = CurTok.SVal; E->V.LVal = CurTok.SVal;
} }

View File

@@ -245,9 +245,6 @@ static void DefineBitFieldData (StructInitData* SI)
static void DefineStrData (Literal* Lit, unsigned Count) static void DefineStrData (Literal* Lit, unsigned Count)
{ {
/* Translate into target charset */
TranslateLiteral (Lit);
/* Output the data */ /* Output the data */
g_defbytes (GetLiteralStr (Lit), Count); g_defbytes (GetLiteralStr (Lit), Count);
} }

View File

@@ -1096,8 +1096,12 @@ void ConsumePragma (void)
/* Skip the _Pragma token */ /* Skip the _Pragma token */
NextToken (); NextToken ();
/* Prevent from translating string literals in _Pragma */
++InPragmaParser;
/* We expect an opening paren */ /* We expect an opening paren */
if (!ConsumeLParen ()) { if (!ConsumeLParen ()) {
--InPragmaParser;
return; return;
} }
@@ -1115,6 +1119,8 @@ void ConsumePragma (void)
ParsePragmaString (); ParsePragmaString ();
} }
--InPragmaParser;
/* Closing paren needed */ /* Closing paren needed */
ConsumeRParen (); ConsumeRParen ();
} }

View File

@@ -70,10 +70,12 @@
static Token SavedTok; /* Saved token */ static Token SavedTok; /* Saved token */
Token CurTok; /* The current token */ Token CurTok; /* The current token */
Token NextTok; /* The next token */ Token NextTok; /* The next token */
int PPParserRunning; /* Is tokenizer used by the preprocessor */ 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 */ /* Translate into target charset */
NextTok.IVal = SignExtendChar (TgtTranslateChar (C)); NextTok.IVal = SignExtendChar (C);
/* Character constants have type int */ /* Character constants have type int */
NextTok.Type = type_int; NextTok.Type = type_int;
@@ -798,6 +800,15 @@ static void GetNextInputToken (void)
{ {
ident token; 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 */ /* Current token is the lookahead token */
if (CurTok.LI) { if (CurTok.LI) {
ReleaseLineInfo (CurTok.LI); ReleaseLineInfo (CurTok.LI);

View File

@@ -219,9 +219,11 @@ struct Token {
const Type* Type; /* Type if integer or float constant */ const Type* Type; /* Type if integer or float constant */
}; };
extern Token CurTok; /* The current token */ extern Token CurTok; /* The current token */
extern Token NextTok; /* The next token */ extern Token NextTok; /* The next token */
extern int PPParserRunning; /* Is tokenizer used by the preprocessor */ extern int PPParserRunning; /* Is tokenizer used by the preprocessor */
extern int NoCharMap; /* Disable literal translation */
extern unsigned InPragmaParser; /* Depth of pragma parser calling */

View File

@@ -72,9 +72,15 @@ void ParseStaticAssert ()
** support the C2X syntax with only an expression. ** support the C2X syntax with only an expression.
*/ */
if (CurTok.Tok == TOK_COMMA) { 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 (); NextToken ();
/* Reenable string literal translation */
NoCharMap = 0;
/* String literal */ /* String literal */
if (CurTok.Tok != TOK_SCONST) { if (CurTok.Tok != TOK_SCONST) {
Error ("String literal expected for static_assert message"); Error ("String literal expected for static_assert message");

View File

@@ -1,9 +1,39 @@
/* Bug #2151 - #pragma causes errors when used within functions */ /* Bug #2151 - #pragma causes errors when used within functions */
#include <stdio.h>
#include <string.h>
#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") #pragma bss-name("BSS1")
int int
#pragma code-name("CODE_WUT") #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 void
_Pragma _Pragma ( _Pragma _Pragma (
@@ -20,9 +50,27 @@ _Pragma _Pragma (
#pragma bss-name("BSS2") #pragma bss-name("BSS2")
static static
#pragma zpsym ("y") #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; 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") #pragma bss-name("BSS")
} }