Fixed compiling with pragmas in the middle of declarations or statements.

This commit is contained in:
acqn
2023-10-04 21:22:04 +08:00
parent 6222cd9115
commit 20c3e994c6
7 changed files with 271 additions and 116 deletions

View File

@@ -111,12 +111,6 @@ static void Parse (void)
continue; continue;
} }
/* Check for a #pragma */
if (CurTok.Tok == TOK_PRAGMA) {
DoPragma ();
continue;
}
/* Check for a _Static_assert */ /* Check for a _Static_assert */
if (CurTok.Tok == TOK_STATIC_ASSERT) { if (CurTok.Tok == TOK_STATIC_ASSERT) {
ParseStaticAssert (); ParseStaticAssert ();

View File

@@ -41,12 +41,11 @@
#include "chartype.h" #include "chartype.h"
#include "segnames.h" #include "segnames.h"
#include "tgttrans.h" #include "tgttrans.h"
#include "xmalloc.h"
/* cc65 */ /* cc65 */
#include "codegen.h" #include "codegen.h"
#include "error.h" #include "error.h"
#include "expr.h"
#include "funcdesc.h"
#include "global.h" #include "global.h"
#include "litpool.h" #include "litpool.h"
#include "scanner.h" #include "scanner.h"
@@ -58,7 +57,7 @@
/*****************************************************************************/ /*****************************************************************************/
/* data */ /* Data */
/*****************************************************************************/ /*****************************************************************************/
@@ -142,6 +141,21 @@ typedef enum {
PP_ERROR, PP_ERROR,
} PushPopResult; } PushPopResult;
/* Effective scope of the pragma.
** This talks about how far the pragma has effects on whenever it shows up,
** even in the middle of an expression, statement or something.
*/
typedef enum {
PES_NONE,
PES_IMM, /* No way back */
PES_EXPR, /* Current expression/declarator */
PES_STMT, /* Current statement/declaration */
PES_SCOPE, /* Current scope */
PES_FUNC, /* Current function */
PES_FILE, /* Current file */
PES_ALL, /* All */
} pragma_scope_t;
/*****************************************************************************/ /*****************************************************************************/
@@ -339,7 +353,7 @@ static void PushInt (IntStack* S, long Val)
static int BoolKeyword (StrBuf* Ident) static int IsBoolKeyword (StrBuf* Ident)
/* Check if the identifier in Ident is a keyword for a boolean value. Currently /* Check if the identifier in Ident is a keyword for a boolean value. Currently
** accepted are true/false/on/off. ** accepted are true/false/on/off.
*/ */
@@ -364,17 +378,92 @@ static int BoolKeyword (StrBuf* Ident)
static void ApplyPragma (int PushPop, IntStack* Stack, long Val)
/* Apply a pragma immediately */
{
if (PushPop > 0) {
/* Push the new value */
PushInt (Stack, Val);
} else if (PushPop < 0) {
/* Pop the old value */
PopInt (Stack);
} else {
/* Set the new value */
IS_Set (Stack, Val);
}
}
static void ApplySegNamePragma (pragma_t Token, int PushPop, const char* Name, unsigned char AddrSize)
/* Process a segname pragma */
{
segment_t Seg = SEG_CODE;
switch (Token) {
case PRAGMA_CODE_NAME:
case PRAGMA_CODESEG:
Seg = SEG_CODE;
break;
case PRAGMA_RODATA_NAME:
case PRAGMA_RODATASEG:
Seg = SEG_RODATA;
break;
case PRAGMA_DATA_NAME:
case PRAGMA_DATASEG:
Seg = SEG_DATA;
break;
case PRAGMA_BSS_NAME:
case PRAGMA_BSSSEG:
Seg = SEG_BSS;
break;
default:
Internal ("Unknown segment name pragma: %02X", Token);
break;
}
/* Set the new name */
if (PushPop > 0) {
PushSegName (Seg, Name);
} else if (PushPop < 0) {
PopSegName (Seg);
} else {
SetSegName (Seg, Name);
}
/* Set the optional address size for the segment if valid */
if (PushPop >= 0 && AddrSize != ADDR_SIZE_INVALID) {
SetSegAddrSize (Name, AddrSize);
}
/* BSS variables are output at the end of the compilation. Don't
** bother to change their segment, now.
*/
if (Seg != SEG_BSS) {
g_segname (Seg);
}
}
/*****************************************************************************/ /*****************************************************************************/
/* Pragma handling functions */ /* Pragma handling functions */
/*****************************************************************************/ /*****************************************************************************/
static void StringPragma (StrBuf* B, void (*Func) (const char*)) static void StringPragma (pragma_scope_t Scope, StrBuf* B, void (*Func) (const char*))
/* Handle a pragma that expects a string parameter */ /* Handle a pragma that expects a string parameter */
{ {
StrBuf S = AUTO_STRBUF_INITIALIZER; StrBuf S = AUTO_STRBUF_INITIALIZER;
/* Only PES_IMM is supported */
CHECK (Scope == PES_IMM);
/* We expect a string here */ /* We expect a string here */
if (GetString (B, &S)) { if (GetString (B, &S)) {
/* Call the given function with the string argument */ /* Call the given function with the string argument */
@@ -387,14 +476,17 @@ static void StringPragma (StrBuf* B, void (*Func) (const char*))
static void SegNamePragma (StrBuf* B, segment_t Seg) static void SegNamePragma (pragma_scope_t Scope, pragma_t Token, StrBuf* B)
/* Handle a pragma that expects a segment name parameter */ /* Handle a pragma that expects a segment name parameter */
{ {
const char* Name; const char* Name;
unsigned char AddrSize = ADDR_SIZE_INVALID; unsigned char AddrSize = ADDR_SIZE_INVALID;
StrBuf S = AUTO_STRBUF_INITIALIZER; StrBuf S = AUTO_STRBUF_INITIALIZER;
StrBuf A = AUTO_STRBUF_INITIALIZER; StrBuf A = AUTO_STRBUF_INITIALIZER;
int Push = 0; int PushPop = 0;
/* Unused at the moment */
(void)Scope;
/* Check for the "push" or "pop" keywords */ /* Check for the "push" or "pop" keywords */
switch (ParsePushPop (B)) { switch (ParsePushPop (B)) {
@@ -403,19 +495,12 @@ static void SegNamePragma (StrBuf* B, segment_t Seg)
break; break;
case PP_PUSH: case PP_PUSH:
Push = 1; PushPop = 1;
break; break;
case PP_POP: case PP_POP:
/* Pop the old value and output it */ /* Pop the old value and output it */
PopSegName (Seg); ApplySegNamePragma (Token, -1, 0, 0);
/* BSS variables are output at the end of the compilation. Don't
** bother to change their segment, now.
*/
if (Seg != SEG_BSS) {
g_segname (Seg);
}
/* Done */ /* Done */
goto ExitPoint; goto ExitPoint;
@@ -454,27 +539,14 @@ static void SegNamePragma (StrBuf* B, segment_t Seg)
/* Get the address size for the segment */ /* Get the address size for the segment */
AddrSize = AddrSizeFromStr (SB_GetConstBuf (&A)); AddrSize = AddrSizeFromStr (SB_GetConstBuf (&A));
/* Set the address size for the segment if valid */ /* Check the address size for the segment */
if (AddrSize != ADDR_SIZE_INVALID) { if (AddrSize == ADDR_SIZE_INVALID) {
SetSegAddrSize (Name, AddrSize); Warning ("Invalid address size for segment");
} else {
Warning ("Invalid address size for segment!");
} }
} }
/* Set the new name and optionally address size */ /* Set the new name and optionally address size */
if (Push) { ApplySegNamePragma (Token, PushPop, Name, AddrSize);
PushSegName (Seg, Name);
} else {
SetSegName (Seg, Name);
}
/* BSS variables are output at the end of the compilation. Don't
** bother to change their segment, now.
*/
if (Seg != SEG_BSS) {
g_segname (Seg);
}
} else { } else {
@@ -484,13 +556,15 @@ static void SegNamePragma (StrBuf* B, segment_t Seg)
} }
ExitPoint: ExitPoint:
/* Call the string buf destructor */ /* Call the string buf destructor */
SB_Done (&S); SB_Done (&S);
SB_Done (&A); SB_Done (&A);
} }
static void WrappedCallPragma (StrBuf* B)
static void WrappedCallPragma (pragma_scope_t Scope, StrBuf* B)
/* Handle the wrapped-call pragma */ /* Handle the wrapped-call pragma */
{ {
StrBuf S = AUTO_STRBUF_INITIALIZER; StrBuf S = AUTO_STRBUF_INITIALIZER;
@@ -498,6 +572,9 @@ static void WrappedCallPragma (StrBuf* B)
long Val; long Val;
SymEntry *Entry; SymEntry *Entry;
/* Only PES_IMM is supported */
CHECK (Scope == PES_IMM);
/* Check for the "push" or "pop" keywords */ /* Check for the "push" or "pop" keywords */
switch (ParsePushPop (B)) { switch (ParsePushPop (B)) {
@@ -573,11 +650,14 @@ ExitPoint:
static void CharMapPragma (StrBuf* B) static void CharMapPragma (pragma_scope_t Scope, StrBuf* B)
/* Change the character map */ /* Change the character map */
{ {
long Index, C; long Index, C;
/* Only PES_IMM is supported */
CHECK (Scope == PES_IMM);
/* Read the character index */ /* Read the character index */
if (!GetNumber (B, &Index)) { if (!GetNumber (B, &Index)) {
return; return;
@@ -619,7 +699,7 @@ static void CharMapPragma (StrBuf* B)
static void WarnPragma (StrBuf* B) static void WarnPragma (pragma_scope_t Scope, StrBuf* B)
/* Enable/disable warnings */ /* Enable/disable warnings */
{ {
long Val; long Val;
@@ -627,6 +707,10 @@ static void WarnPragma (StrBuf* B)
/* A warning name must follow */ /* A warning name must follow */
IntStack* S = GetWarning (B); IntStack* S = GetWarning (B);
/* Only PES_IMM is supported */
CHECK (Scope == PES_IMM);
if (S == 0) { if (S == 0) {
return; return;
} }
@@ -680,48 +764,47 @@ static void WarnPragma (StrBuf* B)
static void FlagPragma (StrBuf* B, IntStack* Stack) static void FlagPragma (pragma_scope_t Scope, pragma_t Token, StrBuf* B, IntStack* Stack)
/* Handle a pragma that expects a boolean parameter */ /* Handle a pragma that expects a boolean parameter */
{ {
StrBuf Ident = AUTO_STRBUF_INITIALIZER; StrBuf Ident = AUTO_STRBUF_INITIALIZER;
long Val; long Val;
int Push; int PushPop = 0;
/* Unused at the moment */
(void)Scope;
(void)Token;
/* Try to read an identifier */ /* Try to read an identifier */
int IsIdent = SB_GetSym (B, &Ident, 0); int IsIdent = SB_GetSym (B, &Ident, 0);
/* Check if we have a first argument named "pop" */ /* Check if we have a first argument named "pop" */
if (IsIdent && SB_CompareStr (&Ident, "pop") == 0) { if (IsIdent && SB_CompareStr (&Ident, "pop") == 0) {
PopInt (Stack); /* Pop the old value and bail out */
ApplyPragma (-1, Stack, 0);
/* No other arguments allowed */ /* No other arguments allowed */
return; return;
} }
/* Check if we have a first argument named "push" */ /* Check if we have a first argument named "push" */
if (IsIdent && SB_CompareStr (&Ident, "push") == 0) { if (IsIdent && SB_CompareStr (&Ident, "push") == 0) {
Push = 1; PushPop = 1;
if (!GetComma (B)) { if (!GetComma (B)) {
goto ExitPoint; goto ExitPoint;
} }
IsIdent = SB_GetSym (B, &Ident, 0); IsIdent = SB_GetSym (B, &Ident, 0);
} else {
Push = 0;
} }
/* Boolean argument follows */ /* Boolean argument follows */
if (IsIdent) { if (IsIdent) {
Val = BoolKeyword (&Ident); Val = IsBoolKeyword (&Ident);
} else if (!GetNumber (B, &Val)) { } else if (!GetNumber (B, &Val)) {
goto ExitPoint; goto ExitPoint;
} }
/* Set/push the new value */ /* Add this pragma and apply it whenever appropriately */
if (Push) { ApplyPragma (PushPop, Stack, Val);
PushInt (Stack, Val);
} else {
IS_Set (Stack, Val);
}
ExitPoint: ExitPoint:
/* Free the identifier */ /* Free the identifier */
@@ -730,12 +813,16 @@ ExitPoint:
static void IntPragma (StrBuf* B, IntStack* Stack, long Low, long High) static void IntPragma (pragma_scope_t Scope, pragma_t Token, StrBuf* B, IntStack* Stack, long Low, long High)
/* Handle a pragma that expects an int parameter */ /* Handle a pragma that expects an int parameter */
{ {
long Val; long Val;
int Push; int Push;
/* Unused at the moment */
(void)Scope;
(void)Token;
/* Check for the "push" or "pop" keywords */ /* Check for the "push" or "pop" keywords */
switch (ParsePushPop (B)) { switch (ParsePushPop (B)) {
@@ -749,7 +836,7 @@ static void IntPragma (StrBuf* B, IntStack* Stack, long Low, long High)
case PP_POP: case PP_POP:
/* Pop the old value and bail out */ /* Pop the old value and bail out */
PopInt (Stack); ApplyPragma (-1, Stack, 0);
return; return;
case PP_ERROR: case PP_ERROR:
@@ -772,31 +859,32 @@ static void IntPragma (StrBuf* B, IntStack* Stack, long Low, long High)
return; return;
} }
/* Set/push the new value */ /* Add this pragma and apply it whenever appropriately */
if (Push) { ApplyPragma (Push, Stack, Val);
PushInt (Stack, Val);
} else {
IS_Set (Stack, Val);
}
} }
static void MakeMessage (const char* Message) static void NoteMessagePragma (const char* Message)
/* Wrapper for printf-like Note() function protected from user-provided format
** specifiers.
*/
{ {
Note ("%s", Message); Note ("%s", Message);
} }
static void ParsePragma (void) static void ParsePragmaString (void)
/* Parse the contents of the _Pragma statement */ /* Parse the contents of _Pragma */
{ {
pragma_t Pragma; pragma_t Pragma;
StrBuf Ident = AUTO_STRBUF_INITIALIZER; StrBuf Ident = AUTO_STRBUF_INITIALIZER;
/* Create a string buffer from the string literal */ /* Create a string buffer from the string literal */
StrBuf B = AUTO_STRBUF_INITIALIZER; StrBuf B = AUTO_STRBUF_INITIALIZER;
SB_Append (&B, GetLiteralStrBuf (CurTok.SVal)); SB_Append (&B, GetLiteralStrBuf (CurTok.SVal));
/* Skip the string token */ /* Skip the string token */
@@ -837,111 +925,130 @@ static void ParsePragma (void)
switch (Pragma) { switch (Pragma) {
case PRAGMA_ALIGN: case PRAGMA_ALIGN:
IntPragma (&B, &DataAlignment, 1, 4096); /* TODO: PES_EXPR (PES_DECL) */
IntPragma (PES_STMT, Pragma, &B, &DataAlignment, 1, 4096);
break; break;
case PRAGMA_ALLOW_EAGER_INLINE: case PRAGMA_ALLOW_EAGER_INLINE:
FlagPragma (&B, &EagerlyInlineFuncs); FlagPragma (PES_STMT, Pragma, &B, &EagerlyInlineFuncs);
break; break;
case PRAGMA_BSSSEG: case PRAGMA_BSSSEG:
Warning ("#pragma bssseg is obsolete, please use #pragma bss-name instead"); Warning ("#pragma bssseg is obsolete, please use #pragma bss-name instead");
/* FALLTHROUGH */ /* FALLTHROUGH */
case PRAGMA_BSS_NAME: case PRAGMA_BSS_NAME:
SegNamePragma (&B, SEG_BSS); /* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
SegNamePragma (PES_FUNC, PRAGMA_BSS_NAME, &B);
break; break;
case PRAGMA_CHARMAP: case PRAGMA_CHARMAP:
CharMapPragma (&B); CharMapPragma (PES_IMM, &B);
break; break;
case PRAGMA_CHECKSTACK: case PRAGMA_CHECKSTACK:
Warning ("#pragma checkstack is obsolete, please use #pragma check-stack instead"); Warning ("#pragma checkstack is obsolete, please use #pragma check-stack instead");
/* FALLTHROUGH */ /* FALLTHROUGH */
case PRAGMA_CHECK_STACK: case PRAGMA_CHECK_STACK:
FlagPragma (&B, &CheckStack); /* TODO: PES_SCOPE maybe? */
FlagPragma (PES_FUNC, Pragma, &B, &CheckStack);
break; break;
case PRAGMA_CODESEG: case PRAGMA_CODESEG:
Warning ("#pragma codeseg is obsolete, please use #pragma code-name instead"); Warning ("#pragma codeseg is obsolete, please use #pragma code-name instead");
/* FALLTHROUGH */ /* FALLTHROUGH */
case PRAGMA_CODE_NAME: case PRAGMA_CODE_NAME:
SegNamePragma (&B, SEG_CODE); /* PES_FUNC is the only sensible option so far */
SegNamePragma (PES_FUNC, PRAGMA_CODE_NAME, &B);
break; break;
case PRAGMA_CODESIZE: case PRAGMA_CODESIZE:
IntPragma (&B, &CodeSizeFactor, 10, 1000); /* PES_EXPR would be optimization nightmare */
IntPragma (PES_STMT, Pragma, &B, &CodeSizeFactor, 10, 1000);
break; break;
case PRAGMA_DATASEG: case PRAGMA_DATASEG:
Warning ("#pragma dataseg is obsolete, please use #pragma data-name instead"); Warning ("#pragma dataseg is obsolete, please use #pragma data-name instead");
/* FALLTHROUGH */ /* FALLTHROUGH */
case PRAGMA_DATA_NAME: case PRAGMA_DATA_NAME:
SegNamePragma (&B, SEG_DATA); /* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
SegNamePragma (PES_FUNC, PRAGMA_DATA_NAME, &B);
break; break;
case PRAGMA_INLINE_STDFUNCS: case PRAGMA_INLINE_STDFUNCS:
FlagPragma (&B, &InlineStdFuncs); /* TODO: PES_EXPR maybe? */
FlagPragma (PES_STMT, Pragma, &B, &InlineStdFuncs);
break; break;
case PRAGMA_LOCAL_STRINGS: case PRAGMA_LOCAL_STRINGS:
FlagPragma (&B, &LocalStrings); /* TODO: PES_STMT or even PES_EXPR */
FlagPragma (PES_FUNC, Pragma, &B, &LocalStrings);
break; break;
case PRAGMA_MESSAGE: case PRAGMA_MESSAGE:
StringPragma (&B, MakeMessage); /* PES_IMM is the only sensible option */
StringPragma (PES_IMM, &B, NoteMessagePragma);
break; break;
case PRAGMA_OPTIMIZE: case PRAGMA_OPTIMIZE:
FlagPragma (&B, &Optimize); /* TODO: PES_STMT or even PES_EXPR maybe? */
FlagPragma (PES_STMT, Pragma, &B, &Optimize);
break; break;
case PRAGMA_REGVARADDR: case PRAGMA_REGVARADDR:
FlagPragma (&B, &AllowRegVarAddr); /* TODO: PES_STMT or even PES_EXPR maybe? */
FlagPragma (PES_FUNC, Pragma, &B, &AllowRegVarAddr);
break; break;
case PRAGMA_REGVARS: case PRAGMA_REGVARS:
Warning ("#pragma regvars is obsolete, please use #pragma register-vars instead"); Warning ("#pragma regvars is obsolete, please use #pragma register-vars instead");
/* FALLTHROUGH */ /* FALLTHROUGH */
case PRAGMA_REGISTER_VARS: case PRAGMA_REGISTER_VARS:
FlagPragma (&B, &EnableRegVars); /* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
FlagPragma (PES_FUNC, Pragma, &B, &EnableRegVars);
break; break;
case PRAGMA_RODATASEG: case PRAGMA_RODATASEG:
Warning ("#pragma rodataseg is obsolete, please use #pragma rodata-name instead"); Warning ("#pragma rodataseg is obsolete, please use #pragma rodata-name instead");
/* FALLTHROUGH */ /* FALLTHROUGH */
case PRAGMA_RODATA_NAME: case PRAGMA_RODATA_NAME:
SegNamePragma (&B, SEG_RODATA); /* TODO: PES_STMT or even PES_EXPR maybe? */
SegNamePragma (PES_FUNC, PRAGMA_RODATA_NAME, &B);
break; break;
case PRAGMA_SIGNEDCHARS: case PRAGMA_SIGNEDCHARS:
Warning ("#pragma signedchars is obsolete, please use #pragma signed-chars instead"); Warning ("#pragma signedchars is obsolete, please use #pragma signed-chars instead");
/* FALLTHROUGH */ /* FALLTHROUGH */
case PRAGMA_SIGNED_CHARS: case PRAGMA_SIGNED_CHARS:
FlagPragma (&B, &SignedChars); /* TODO: PES_STMT or even PES_EXPR maybe? */
FlagPragma (PES_FUNC, Pragma, &B, &SignedChars);
break; break;
case PRAGMA_STATICLOCALS: case PRAGMA_STATICLOCALS:
Warning ("#pragma staticlocals is obsolete, please use #pragma static-locals instead"); Warning ("#pragma staticlocals is obsolete, please use #pragma static-locals instead");
/* FALLTHROUGH */ /* FALLTHROUGH */
case PRAGMA_STATIC_LOCALS: case PRAGMA_STATIC_LOCALS:
FlagPragma (&B, &StaticLocals); /* TODO: PES_STMT or even PES_EXPR (PES_DECL) maybe? */
FlagPragma (PES_FUNC, Pragma, &B, &StaticLocals);
break; break;
case PRAGMA_WRAPPED_CALL: case PRAGMA_WRAPPED_CALL:
WrappedCallPragma(&B); /* PES_IMM is the only sensible option */
WrappedCallPragma (PES_IMM, &B);
break; break;
case PRAGMA_WARN: case PRAGMA_WARN:
WarnPragma (&B); /* PES_IMM is the only sensible option */
WarnPragma (PES_IMM, &B);
break; break;
case PRAGMA_WRITABLE_STRINGS: case PRAGMA_WRITABLE_STRINGS:
FlagPragma (&B, &WritableStrings); /* TODO: PES_STMT or even PES_EXPR maybe? */
FlagPragma (PES_FUNC, Pragma, &B, &WritableStrings);
break; break;
case PRAGMA_ZPSYM: case PRAGMA_ZPSYM:
StringPragma (&B, MakeZPSym); /* PES_IMM is the only sensible option */
StringPragma (PES_IMM, &B, MakeZPSym);
break; break;
default: default:
@@ -975,10 +1082,18 @@ ExitPoint:
void DoPragma (void) /*****************************************************************************/
/* Handle pragmas. These come always in form of the new C99 _Pragma() operator. */ /* Code */
/*****************************************************************************/
void ConsumePragma (void)
/* Parse a pragma. The pragma comes always in the form of the new C99 _Pragma()
** operator.
*/
{ {
/* Skip the token itself */ /* Skip the _Pragma token */
NextToken (); NextToken ();
/* We expect an opening paren */ /* We expect an opening paren */
@@ -988,7 +1103,6 @@ void DoPragma (void)
/* String literal */ /* String literal */
if (CurTok.Tok != TOK_SCONST) { if (CurTok.Tok != TOK_SCONST) {
/* Print a diagnostic */ /* Print a diagnostic */
Error ("String literal expected"); Error ("String literal expected");
@@ -996,11 +1110,9 @@ void DoPragma (void)
** enclosing paren, or a semicolon. ** enclosing paren, or a semicolon.
*/ */
PragmaErrorSkip (); PragmaErrorSkip ();
} else { } else {
/* Parse the pragma */
/* Parse the _Pragma statement */ ParsePragmaString ();
ParsePragma ();
} }
/* Closing paren needed */ /* Closing paren needed */

View File

@@ -44,8 +44,10 @@
void DoPragma (void); void ConsumePragma (void);
/* Handle pragmas. These come always in form of the new C99 _Pragma() operator. */ /* Parse a pragma. The pragma comes always in the form of the new C99 _Pragma()
** operator.
*/

View File

@@ -56,6 +56,7 @@
#include "ident.h" #include "ident.h"
#include "input.h" #include "input.h"
#include "litpool.h" #include "litpool.h"
#include "pragma.h"
#include "preproc.h" #include "preproc.h"
#include "scanner.h" #include "scanner.h"
#include "standard.h" #include "standard.h"
@@ -800,36 +801,30 @@ static void NumericConst (void)
void NextToken (void) static void GetNextInputToken (void)
/* Get next token from input stream */ /* Get next token from input stream */
{ {
ident token; ident token;
/* We have to skip white space here before shifting tokens, since the /* We have to skip white space here before shifting tokens, since the
** tokens and the current line info is invalid at startup and will get ** tokens and the current line info is invalid at startup and will get
** initialized by reading the first time from the file. Remember if ** initialized by reading the first time from the file. Remember if we
** we were at end of input and handle that later. ** were at end of input and handle that later.
*/ */
int GotEOF = (SkipWhite() == 0); int GotEOF = (SkipWhite () == 0);
/* Current token is the lookahead token */ /* Current token is the lookahead token */
if (CurTok.LI) { if (CurTok.LI) {
ReleaseLineInfo (CurTok.LI); ReleaseLineInfo (CurTok.LI);
} }
CurTok = NextTok;
/* When reading the first time from the file, the line info in NextTok, /* Get the current token */
** which was copied to CurTok is invalid. Since the information from CurTok = NextTok;
** the token is used for error messages, we must make it valid.
*/
if (CurTok.LI == 0) {
CurTok.LI = UseLineInfo (GetCurLineInfo ());
}
/* Remember the starting position of the next token */ /* Remember the starting position of the next token */
NextTok.LI = UseLineInfo (GetCurLineInfo ()); NextTok.LI = UseLineInfo (GetCurLineInfo ());
/* Now handle end of input. */ /* Now handle end of input */
if (GotEOF) { if (GotEOF) {
/* End of file reached */ /* End of file reached */
NextTok.Tok = TOK_CEOF; NextTok.Tok = TOK_CEOF;
@@ -859,7 +854,8 @@ void NextToken (void)
if (!PPParserRunning) { if (!PPParserRunning) {
/* Check for a keyword */ /* Check for a keyword */
if ((NextTok.Tok = FindKey (token)) != TOK_IDENT) { NextTok.Tok = FindKey (token);
if (NextTok.Tok != TOK_IDENT) {
/* Reserved word found */ /* Reserved word found */
return; return;
} }
@@ -1117,7 +1113,31 @@ void NextToken (void)
UnknownChar (CurC); UnknownChar (CurC);
} }
}
void NextToken (void)
/* Get next non-pragma token from input stream consuming any pragmas
** encountered. Adjacent string literal tokens will be concatenated.
*/
{
/* When reading the first time from the file, the line info in NextTok,
** which will be copied to CurTok is invalid. Since the information from
** the token is used for error messages, we must make it valid.
*/
if (NextTok.LI == 0) {
NextTok.LI = UseLineInfo (GetCurLineInfo ());
}
/* Read the next token from the file */
GetNextInputToken ();
/* Consume all pragmas at hand, including those nested in a _Pragma() */
if (CurTok.Tok == TOK_PRAGMA) {
/* Repeated and/or nested _Pragma()'s will be handled recursively */
ConsumePragma ();
}
} }

View File

@@ -299,7 +299,9 @@ void CopyPPNumber (StrBuf* Target);
/* Copy a pp-number from the input to Target */ /* Copy a pp-number from the input to Target */
void NextToken (void); void NextToken (void);
/* Get next token from input stream */ /* Get next non-pragma token from input stream consuming any pragmas
** encountered. Adjacent string literal tokens will be concatenated.
*/
void SkipTokens (const token_t* TokenList, unsigned TokenCount); void SkipTokens (const token_t* TokenList, unsigned TokenCount);
/* Skip tokens until we reach TOK_CEOF or a token in the given token list. /* Skip tokens until we reach TOK_CEOF or a token in the given token list.

View File

@@ -735,10 +735,6 @@ int AnyStatement (int* PendingToken)
GotBreak = 1; GotBreak = 1;
break; break;
case TOK_PRAGMA:
DoPragma ();
break;
case TOK_SEMI: case TOK_SEMI:
/* Empty statement. Ignore it */ /* Empty statement. Ignore it */
CheckSemi (PendingToken); CheckSemi (PendingToken);

29
test/val/bug2151.c Normal file
View File

@@ -0,0 +1,29 @@
/* Bug #2151 - #pragma causes errors when used within functions */
#pragma bss-name("BSS1")
int
#pragma code-name("CODE_WUT")
main _Pragma("message(\"_Pragma note\")")
(
void
_Pragma _Pragma (
#pragma message("nested message 1")
"message(\"nested message 2\")"
)
(
"message(\"_Pragma in function parentheses\")")
#pragma code-name("CODE")
)
#pragma bss-name("BSS")
{
extern int y;
#pragma bss-name("BSS2")
static
#pragma zpsym ("y")
int x; // TODO: currently in "BSS", but supposed to be in "BSS2"?
x = 0;
return x + y;
#pragma bss-name("BSS")
}
int y;