X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcc65%2Fpragma.c;h=01e4ea3cf0d85a02b77d713e647fed2fb1d6708b;hb=f266612697b213f2f74027eb5b2605b19a97d6d7;hp=ff0532b656c2a20c140361c30499f8710594cda2;hpb=d0ea9f34b6ea2e460b7fbfe15f629f4fc944eb35;p=cc65 diff --git a/src/cc65/pragma.c b/src/cc65/pragma.c index ff0532b65..01e4ea3cf 100644 --- a/src/cc65/pragma.c +++ b/src/cc65/pragma.c @@ -1,15 +1,15 @@ /*****************************************************************************/ /* */ -/* pragma.c */ +/* pragma.c */ /* */ -/* Pragma handling for the cc65 C compiler */ +/* Pragma handling for the cc65 C compiler */ /* */ /* */ /* */ -/* (C) 1998-2004 Ullrich von Bassewitz */ -/* Römerstraße 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 1998-2011, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -37,6 +37,7 @@ #include /* common */ +#include "chartype.h" #include "segnames.h" #include "tgttrans.h" @@ -54,50 +55,86 @@ /*****************************************************************************/ -/* data */ +/* data */ /*****************************************************************************/ /* Tokens for the #pragmas */ typedef enum { - PR_ILLEGAL = -1, - PR_BSSSEG, - PR_CHARMAP, - PR_CHECKSTACK, - PR_CODESEG, - PR_DATASEG, - PR_REGVARADDR, - PR_REGVARS, - PR_RODATASEG, - PR_SIGNEDCHARS, - PR_STATICLOCALS, - PR_ZPSYM, - PR_COUNT + PRAGMA_ILLEGAL = -1, + PRAGMA_ALIGN, + PRAGMA_BSS_NAME, + PRAGMA_BSSSEG, /* obsolete */ + PRAGMA_CHARMAP, + PRAGMA_CHECK_STACK, + PRAGMA_CHECKSTACK, /* obsolete */ + PRAGMA_CODE_NAME, + PRAGMA_CODESEG, /* obsolete */ + PRAGMA_CODESIZE, + PRAGMA_DATA_NAME, + PRAGMA_DATASEG, /* obsolete */ + PRAGMA_LOCAL_STRINGS, + PRAGMA_OPTIMIZE, + PRAGMA_REGVARADDR, + PRAGMA_REGISTER_VARS, + PRAGMA_REGVARS, /* obsolete */ + PRAGMA_RODATA_NAME, + PRAGMA_RODATASEG, /* obsolete */ + PRAGMA_SIGNED_CHARS, + PRAGMA_SIGNEDCHARS, /* obsolete */ + PRAGMA_STATIC_LOCALS, + PRAGMA_STATICLOCALS, /* obsolete */ + PRAGMA_WARN, + PRAGMA_WRITABLE_STRINGS, + PRAGMA_ZPSYM, + PRAGMA_COUNT } pragma_t; /* Pragma table */ static const struct Pragma { - const char* Key; /* Keyword */ - pragma_t Tok; /* Token */ -} Pragmas[PR_COUNT] = { - { "bssseg", PR_BSSSEG }, - { "charmap", PR_CHARMAP }, - { "checkstack", PR_CHECKSTACK }, - { "codeseg", PR_CODESEG }, - { "dataseg", PR_DATASEG }, - { "regvaraddr", PR_REGVARADDR }, - { "regvars", PR_REGVARS }, - { "rodataseg", PR_RODATASEG }, - { "signedchars", PR_SIGNEDCHARS }, - { "staticlocals", PR_STATICLOCALS }, - { "zpsym", PR_ZPSYM }, + const char* Key; /* Keyword */ + pragma_t Tok; /* Token */ +} Pragmas[PRAGMA_COUNT] = { + { "align", PRAGMA_ALIGN }, + { "bss-name", PRAGMA_BSS_NAME }, + { "bssseg", PRAGMA_BSSSEG }, /* obsolete */ + { "charmap", PRAGMA_CHARMAP }, + { "check-stack", PRAGMA_CHECK_STACK }, + { "checkstack", PRAGMA_CHECKSTACK }, /* obsolete */ + { "code-name", PRAGMA_CODE_NAME }, + { "codeseg", PRAGMA_CODESEG }, /* obsolete */ + { "codesize", PRAGMA_CODESIZE }, + { "data-name", PRAGMA_DATA_NAME }, + { "dataseg", PRAGMA_DATASEG }, /* obsolete */ + { "local-strings", PRAGMA_LOCAL_STRINGS }, + { "optimize", PRAGMA_OPTIMIZE }, + { "register-vars", PRAGMA_REGISTER_VARS }, + { "regvaraddr", PRAGMA_REGVARADDR }, + { "regvars", PRAGMA_REGVARS }, /* obsolete */ + { "rodata-name", PRAGMA_RODATA_NAME }, + { "rodataseg", PRAGMA_RODATASEG }, /* obsolete */ + { "signed-chars", PRAGMA_SIGNED_CHARS }, + { "signedchars", PRAGMA_SIGNEDCHARS }, /* obsolete */ + { "static-locals", PRAGMA_STATIC_LOCALS }, + { "staticlocals", PRAGMA_STATICLOCALS }, /* obsolete */ + { "warn", PRAGMA_WARN }, + { "writable-strings", PRAGMA_WRITABLE_STRINGS }, + { "zpsym", PRAGMA_ZPSYM }, }; +/* Result of ParsePushPop */ +typedef enum { + PP_NONE, + PP_POP, + PP_PUSH, + PP_ERROR, +} PushPopResult; + /*****************************************************************************/ -/* Code */ +/* Helper functions */ /*****************************************************************************/ @@ -121,33 +158,220 @@ static int CmpKey (const void* Key, const void* Elem) -static pragma_t FindPragma (const char* Key) -/* Find a pragma and return the token. Return PR_ILLEGAL if the keyword is +static pragma_t FindPragma (const StrBuf* Key) +/* Find a pragma and return the token. Return PRAGMA_ILLEGAL if the keyword is * not a valid pragma. */ { struct Pragma* P; - P = bsearch (Key, Pragmas, PR_COUNT, sizeof (Pragmas[0]), CmpKey); - return P? P->Tok : PR_ILLEGAL; + P = bsearch (SB_GetConstBuf (Key), Pragmas, PRAGMA_COUNT, sizeof (Pragmas[0]), CmpKey); + return P? P->Tok : PRAGMA_ILLEGAL; +} + + + +static int GetComma (StrBuf* B) +/* Expects and skips a comma in B. Prints an error and returns zero if no + * comma is found. Return a value <> 0 otherwise. + */ +{ + SB_SkipWhite (B); + if (SB_Get (B) != ',') { + Error ("Comma expected"); + return 0; + } + SB_SkipWhite (B); + return 1; +} + + + +static int GetString (StrBuf* B, StrBuf* S) +/* Expects and skips a string in B. Prints an error and returns zero if no + * string is found. Returns a value <> 0 otherwise. + */ +{ + if (!SB_GetString (B, S)) { + Error ("String literal expected"); + return 0; + } + return 1; +} + + + +static int GetNumber (StrBuf* B, long* Val) +/* Expects and skips a number in B. Prints an eror and returns zero if no + * number is found. Returns a value <> 0 otherwise. + */ +{ + if (!SB_GetNumber (B, Val)) { + Error ("Constant integer expected"); + return 0; + } + return 1; +} + + + +static IntStack* GetWarning (StrBuf* B) +/* Get a warning name from the string buffer. Returns a pointer to the intstack + * that holds the state of the warning, and NULL in case of errors. The + * function will output error messages in case of problems. + */ +{ + IntStack* S = 0; + StrBuf W = AUTO_STRBUF_INITIALIZER; + + /* The warning name is a symbol but the '-' char is allowed within */ + if (SB_GetSym (B, &W, "-")) { + + /* Map the warning name to an IntStack that contains its state */ + S = FindWarning (SB_GetConstBuf (&W)); + + /* Handle errors */ + if (S == 0) { + Error ("Pragma expects a warning name as first argument"); + } + } + + /* Deallocate the string */ + SB_Done (&W); + + /* Done */ + return S; +} + + + +static int HasStr (StrBuf* B, const char* E) +/* Checks if E follows in B. If so, skips it and returns true */ +{ + unsigned Len = strlen (E); + if (SB_GetLen (B) - SB_GetIndex (B) >= Len) { + if (strncmp (SB_GetConstBuf (B) + SB_GetIndex (B), E, Len) == 0) { + /* Found */ + SB_SkipMultiple (B, Len); + return 1; + } + } + return 0; +} + + + +static PushPopResult ParsePushPop (StrBuf* B) +/* Check for and parse the "push" and "pop" keywords. In case of "push", a + * following comma is expected and skipped. + */ +{ + StrBuf Ident = AUTO_STRBUF_INITIALIZER; + PushPopResult Res = PP_NONE; + + /* Remember the current string index, so we can go back in case of errors */ + unsigned Index = SB_GetIndex (B); + + /* Try to read an identifier */ + if (SB_GetSym (B, &Ident, 0)) { + + /* Check if we have a first argument named "pop" */ + if (SB_CompareStr (&Ident, "pop") == 0) { + + Res = PP_POP; + + /* Check if we have a first argument named "push" */ + } else if (SB_CompareStr (&Ident, "push") == 0) { + + Res = PP_PUSH; + + /* Skip the following comma */ + if (!GetComma (B)) { + /* Error already flagged by GetComma */ + Res = PP_ERROR; + } + + } else { + + /* Unknown keyword, roll back */ + SB_SetIndex (B, Index); + } + } + + /* Free the string buffer and return the result */ + SB_Done (&Ident); + return Res; } +static void PopInt (IntStack* S) +/* Pops an integer from an IntStack. Prints an error if the stack is empty */ +{ + if (IS_GetCount (S) < 2) { + Error ("Cannot pop, stack is empty"); + } else { + IS_Drop (S); + } +} + + + +static void PushInt (IntStack* S, long Val) +/* Pushes an integer onto an IntStack. Prints an error if the stack is full */ +{ + if (IS_IsFull (S)) { + Error ("Cannot push: stack overflow"); + } else { + IS_Push (S, Val); + } +} + + + +static int BoolKeyword (StrBuf* Ident) +/* Check if the identifier in Ident is a keyword for a boolean value. Currently + * accepted are true/false/on/off. + */ +{ + if (SB_CompareStr (Ident, "true") == 0) { + return 1; + } + if (SB_CompareStr (Ident, "on") == 0) { + return 1; + } + if (SB_CompareStr (Ident, "false") == 0) { + return 0; + } + if (SB_CompareStr (Ident, "off") == 0) { + return 0; + } + + /* Error */ + Error ("Pragma argument must be one of `on', `off', `true' or `false'"); + return 0; +} + + + +/*****************************************************************************/ +/* Pragma handling functions */ +/*****************************************************************************/ + + + static void StringPragma (StrBuf* B, void (*Func) (const char*)) /* Handle a pragma that expects a string parameter */ { - StrBuf S; + StrBuf S = AUTO_STRBUF_INITIALIZER; /* We expect a string here */ - if (SB_GetString (B, &S)) { - /* Call the given function with the string argument */ - Func (SB_GetConstBuf (&S)); - } else { - Error ("String literal expected"); + if (GetString (B, &S)) { + /* Call the given function with the string argument */ + Func (SB_GetConstBuf (&S)); } /* Call the string buf destructor */ - DoneStrBuf (&S); + SB_Done (&S); } @@ -155,32 +379,66 @@ static void StringPragma (StrBuf* B, void (*Func) (const char*)) static void SegNamePragma (StrBuf* B, segment_t Seg) /* Handle a pragma that expects a segment name parameter */ { - StrBuf S; + StrBuf S = AUTO_STRBUF_INITIALIZER; + const char* Name; + + /* Check for the "push" or "pop" keywords */ + int Push = 0; + switch (ParsePushPop (B)) { - if (SB_GetString (B, &S)) { + case PP_NONE: + break; - /* Get the string */ - const char* Name = SB_GetConstBuf (&S); + case PP_PUSH: + Push = 1; + break; - /* Check if the name is valid */ - if (ValidSegName (Name)) { + case PP_POP: + /* Pop the old value and output it */ + PopSegName (Seg); + g_segname (Seg); - /* Set the new name */ - g_segname (Seg, Name); + /* Done */ + goto ExitPoint; - } else { + case PP_ERROR: + /* Bail out */ + goto ExitPoint; - /* Segment name is invalid */ - Error ("Illegal segment name: `%s'", Name); + default: + Internal ("Invalid result from ParsePushPop"); - } + } + + /* A string argument must follow */ + if (!GetString (B, &S)) { + goto ExitPoint; + } + + /* Get the string */ + Name = SB_GetConstBuf (&S); + + /* Check if the name is valid */ + if (ValidSegName (Name)) { + + /* Set the new name */ + if (Push) { + PushSegName (Seg, Name); + } else { + SetSegName (Seg, Name); + } + g_segname (Seg); } else { - Error ("String literal expected"); + + /* Segment name is invalid */ + Error ("Illegal segment name: `%s'", Name); + } +ExitPoint: /* Call the string buf destructor */ - DoneStrBuf (&S); + SB_Done (&S); } @@ -191,29 +449,36 @@ static void CharMapPragma (StrBuf* B) long Index, C; /* Read the character index */ - if (!SB_GetNumber (B, &Index)) { + if (!GetNumber (B, &Index)) { return; } if (Index < 1 || Index > 255) { - Error ("Character index out of range"); - return; + if (Index == 0) { + /* For groepaz */ + Error ("Remapping 0 is not allowed"); + } else { + Error ("Character index out of range"); + } + return; } /* Comma follows */ - SB_SkipWhite (B); - if (SB_Get (B) != ',') { - Error ("Comma expected"); + if (!GetComma (B)) { return; } - SB_SkipWhite (B); /* Read the character code */ - if (!SB_GetNumber (B, &C)) { + if (!GetNumber (B, &C)) { return; } if (C < 1 || C > 255) { - Error ("Character code out of range"); - return; + if (C == 0) { + /* For groepaz */ + Error ("Remapping 0 is not allowed"); + } else { + Error ("Character code out of range"); + } + return; } /* Remap the character */ @@ -222,62 +487,162 @@ static void CharMapPragma (StrBuf* B) +static void WarnPragma (StrBuf* B) +/* Enable/disable warnings */ +{ + long Val; + int Push; + + /* A warning name must follow */ + IntStack* S = GetWarning (B); + if (S == 0) { + return; + } + + /* Comma follows */ + if (!GetComma (B)) { + return; + } + + /* Check for the "push" or "pop" keywords */ + switch (ParsePushPop (B)) { + + case PP_NONE: + Push = 0; + break; + + case PP_PUSH: + Push = 1; + break; + + case PP_POP: + /* Pop the old value and bail out */ + PopInt (S); + return; + + case PP_ERROR: + /* Bail out */ + return; + + default: + Internal ("Invalid result from ParsePushPop"); + } + + /* Boolean argument follows */ + if (HasStr (B, "true") || HasStr (B, "on")) { + Val = 1; + } else if (HasStr (B, "false") || HasStr (B, "off")) { + Val = 0; + } else if (!SB_GetNumber (B, &Val)) { + Error ("Invalid pragma argument"); + return; + } + + /* Set/push the new value */ + if (Push) { + PushInt (S, Val); + } else { + IS_Set (S, Val); + } +} + + + static void FlagPragma (StrBuf* B, IntStack* Stack) /* Handle a pragma that expects a boolean paramater */ { - ident Ident; - long Val; - int Push; + StrBuf Ident = AUTO_STRBUF_INITIALIZER; + long Val; + int Push; + /* Try to read an identifier */ - int IsIdent = SB_GetSym (B, Ident); + int IsIdent = SB_GetSym (B, &Ident, 0); /* Check if we have a first argument named "pop" */ - if (IsIdent && strcmp (Ident, "pop") == 0) { - if (IS_GetCount (Stack) < 2) { - Error ("Cannot pop, stack is empty"); - } else { - (void) IS_Pop (Stack); - } + if (IsIdent && SB_CompareStr (&Ident, "pop") == 0) { + PopInt (Stack); /* No other arguments allowed */ return; } /* Check if we have a first argument named "push" */ - if (IsIdent && strcmp (Ident, "push") == 0) { + if (IsIdent && SB_CompareStr (&Ident, "push") == 0) { Push = 1; - SB_SkipWhite (B); - if (SB_Get (B) != ',') { - Error ("Comma expected"); - return; + if (!GetComma (B)) { + goto ExitPoint; } - SB_SkipWhite (B); - IsIdent = SB_GetSym (B, Ident); + IsIdent = SB_GetSym (B, &Ident, 0); } else { Push = 0; } /* Boolean argument follows */ if (IsIdent) { - if (strcmp (Ident, "true") == 0 || strcmp (Ident, "on") == 0) { - Val = 1; - } else if (strcmp (Ident, "false") == 0 || strcmp (Ident, "off") == 0) { - Val = 0; - } else { - Error ("Pragma argument must be one of `on', `off', `true' or `false'"); - } - } else if (!SB_GetNumber (B, &Val)) { - Error ("Invalid pragma argument"); + Val = BoolKeyword (&Ident); + } else if (!GetNumber (B, &Val)) { + goto ExitPoint; + } + + /* Set/push the new value */ + if (Push) { + PushInt (Stack, Val); + } else { + IS_Set (Stack, Val); + } + +ExitPoint: + /* Free the identifier */ + SB_Done (&Ident); +} + + + +static void IntPragma (StrBuf* B, IntStack* Stack, long Low, long High) +/* Handle a pragma that expects an int paramater */ +{ + long Val; + int Push; + + /* Check for the "push" or "pop" keywords */ + switch (ParsePushPop (B)) { + + case PP_NONE: + Push = 0; + break; + + case PP_PUSH: + Push = 1; + break; + + case PP_POP: + /* Pop the old value and bail out */ + PopInt (Stack); + return; + + case PP_ERROR: + /* Bail out */ + return; + + default: + Internal ("Invalid result from ParsePushPop"); + + } + + /* Integer argument follows */ + if (!GetNumber (B, &Val)) { + return; + } + + /* Check the argument */ + if (Val < Low || Val > High) { + Error ("Pragma argument out of bounds (%ld-%ld)", Low, High); return; } /* Set/push the new value */ if (Push) { - if (IS_IsFull (Stack)) { - Error ("Cannot push: stack overflow"); - } else { - IS_Push (Stack, Val); - } + PushInt (Stack, Val); } else { IS_Set (Stack, Val); } @@ -289,47 +654,41 @@ static void ParsePragma (void) /* Parse the contents of the _Pragma statement */ { pragma_t Pragma; - ident Ident; + StrBuf Ident = AUTO_STRBUF_INITIALIZER; /* Create a string buffer from the string literal */ StrBuf B = AUTO_STRBUF_INITIALIZER; - GetLiteralStrBuf (&B, CurTok.IVal); - - /* Reset the string pointer, effectivly clearing the string from the - * string table. Since we're working with one token lookahead, this - * will fail if the next token is also a string token, but that's a - * syntax error anyway, because we expect a right paren. - */ - ResetLiteralPoolOffs (CurTok.IVal); + SB_Append (&B, GetLiteralStrBuf (CurTok.SVal)); /* Skip the string token */ NextToken (); /* Get the pragma name from the string */ SB_SkipWhite (&B); - if (!SB_GetSym (&B, Ident)) { + if (!SB_GetSym (&B, &Ident, "-")) { Error ("Invalid pragma"); - return; + goto ExitPoint; } /* Search for the name */ - Pragma = FindPragma (Ident); + Pragma = FindPragma (&Ident); /* Do we know this pragma? */ - if (Pragma == PR_ILLEGAL) { - /* According to the ANSI standard, we're not allowed to generate errors - * for unknown pragmas, however, we're allowed to warn - and we will - * do so. Otherwise one typo may give you hours of bug hunting... - */ - Warning ("Unknown pragma `%s'", Ident); - return; + if (Pragma == PRAGMA_ILLEGAL) { + /* According to the ANSI standard, we're not allowed to generate errors + * for unknown pragmas, but warn about them if enabled (the default). + */ + if (IS_Get (&WarnUnknownPragma)) { + Warning ("Unknown pragma `%s'", SB_GetConstBuf (&Ident)); + } + goto ExitPoint; } /* Check for an open paren */ SB_SkipWhite (&B); if (SB_Get (&B) != '(') { Error ("'(' expected"); - return; + goto ExitPoint; } /* Skip white space before the argument */ @@ -338,59 +697,107 @@ static void ParsePragma (void) /* Switch for the different pragmas */ switch (Pragma) { - case PR_BSSSEG: - SegNamePragma (&B, SEG_BSS); - break; - - case PR_CHARMAP: - CharMapPragma (&B); - break; - - case PR_CHECKSTACK: - FlagPragma (&B, &CheckStack); - break; - - case PR_CODESEG: - SegNamePragma (&B, SEG_CODE); - break; - - case PR_DATASEG: - SegNamePragma (&B, SEG_DATA); - break; - - case PR_REGVARADDR: - FlagPragma (&B, &AllowRegVarAddr); - break; - - case PR_REGVARS: - FlagPragma (&B, &EnableRegVars); - break; - - case PR_RODATASEG: - SegNamePragma (&B, SEG_RODATA); - break; - - case PR_SIGNEDCHARS: - FlagPragma (&B, &SignedChars); - break; - - case PR_STATICLOCALS: - FlagPragma (&B, &StaticLocals); - break; - - case PR_ZPSYM: - StringPragma (&B, MakeZPSym); - break; - - default: - Internal ("Invalid pragma"); + case PRAGMA_ALIGN: + IntPragma (&B, &DataAlignment, 1, 4096); + break; + + case PRAGMA_BSSSEG: + Warning ("#pragma bssseg is obsolete, please use #pragma bss-name instead"); + /* FALLTHROUGH */ + case PRAGMA_BSS_NAME: + SegNamePragma (&B, SEG_BSS); + break; + + case PRAGMA_CHARMAP: + CharMapPragma (&B); + break; + + case PRAGMA_CHECKSTACK: + Warning ("#pragma checkstack is obsolete, please use #pragma check-stack instead"); + /* FALLTHROUGH */ + case PRAGMA_CHECK_STACK: + FlagPragma (&B, &CheckStack); + break; + + case PRAGMA_CODESEG: + Warning ("#pragma codeseg is obsolete, please use #pragma code-name instead"); + /* FALLTHROUGH */ + case PRAGMA_CODE_NAME: + SegNamePragma (&B, SEG_CODE); + break; + + case PRAGMA_CODESIZE: + IntPragma (&B, &CodeSizeFactor, 10, 1000); + break; + + case PRAGMA_DATASEG: + Warning ("#pragma dataseg is obsolete, please use #pragma data-name instead"); + /* FALLTHROUGH */ + case PRAGMA_DATA_NAME: + SegNamePragma (&B, SEG_DATA); + break; + + case PRAGMA_LOCAL_STRINGS: + FlagPragma (&B, &LocalStrings); + break; + + case PRAGMA_OPTIMIZE: + FlagPragma (&B, &Optimize); + break; + + case PRAGMA_REGVARADDR: + FlagPragma (&B, &AllowRegVarAddr); + break; + + case PRAGMA_REGVARS: + Warning ("#pragma regvars is obsolete, please use #pragma register-vars instead"); + /* FALLTHROUGH */ + case PRAGMA_REGISTER_VARS: + FlagPragma (&B, &EnableRegVars); + break; + + case PRAGMA_RODATASEG: + Warning ("#pragma rodataseg is obsolete, please use #pragma rodata-name instead"); + /* FALLTHROUGH */ + case PRAGMA_RODATA_NAME: + SegNamePragma (&B, SEG_RODATA); + break; + + case PRAGMA_SIGNEDCHARS: + Warning ("#pragma signedchars is obsolete, please use #pragma signed-chars instead"); + /* FALLTHROUGH */ + case PRAGMA_SIGNED_CHARS: + FlagPragma (&B, &SignedChars); + break; + + case PRAGMA_STATICLOCALS: + Warning ("#pragma staticlocals is obsolete, please use #pragma static-locals instead"); + /* FALLTHROUGH */ + case PRAGMA_STATIC_LOCALS: + FlagPragma (&B, &StaticLocals); + break; + + case PRAGMA_WARN: + WarnPragma (&B); + break; + + case PRAGMA_WRITABLE_STRINGS: + FlagPragma (&B, &WritableStrings); + break; + + case PRAGMA_ZPSYM: + StringPragma (&B, MakeZPSym); + break; + + default: + Internal ("Invalid pragma"); } /* Closing paren expected */ SB_SkipWhite (&B); if (SB_Get (&B) != ')') { Error ("')' expected"); - return; + goto ExitPoint; } SB_SkipWhite (&B); @@ -405,8 +812,10 @@ static void ParsePragma (void) Error ("Unexpected input following pragma directive"); } - /* Release the StrBuf */ - DoneStrBuf (&B); +ExitPoint: + /* Release the string buffers */ + SB_Done (&B); + SB_Done (&Ident); } @@ -419,29 +828,26 @@ void DoPragma (void) /* We expect an opening paren */ if (!ConsumeLParen ()) { - return; + return; } /* String literal */ if (CurTok.Tok != TOK_SCONST) { - /* Print a diagnostic */ - Error ("String literal expected"); + /* Print a diagnostic */ + Error ("String literal expected"); - /* Try some smart error recovery: Skip tokens until we reach the - * enclosing paren, or a semicolon. - */ - PragmaErrorSkip (); + /* Try some smart error recovery: Skip tokens until we reach the + * enclosing paren, or a semicolon. + */ + PragmaErrorSkip (); } else { - /* Parse the _Pragma statement */ - ParsePragma (); + /* Parse the _Pragma statement */ + ParsePragma (); } /* Closing paren needed */ ConsumeRParen (); } - - -