X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fpreproc.c;h=8922c7733161eb0ff97330c5b17ce575c88aaba7;hb=92a4c51753a0b66c923a777fcd44c50f26717cbd;hp=f7b44a1467b870eeae20e83b9ecc2c01a94b69eb;hpb=cc83744882b694fd42c8ce1b9da075f5d1e9ba1b;p=cc65 diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index f7b44a146..8922c7733 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -8,6 +8,7 @@ /* common */ #include "chartype.h" +#include "check.h" #include "print.h" #include "xmalloc.h" @@ -39,18 +40,22 @@ static int Pass1 (const char* From, char* To); /*****************************************************************************/ -/* data */ +/* Data */ /*****************************************************************************/ -/* Set when the pp calls expr() recursively */ +/* Set when the preprocessor calls expr() recursively */ unsigned char Preprocessing = 0; /* Management data for #if */ -#define N_IFDEF 16 -static int i_ifdef = -1; -static char s_ifdef[N_IFDEF]; +#define MAX_IFS 64 +#define IFCOND_NONE 0x00U +#define IFCOND_SKIP 0x01U +#define IFCOND_ELSE 0x02U +#define IFCOND_NEEDTERM 0x04U +static unsigned char IfStack[MAX_IFS]; +static int IfIndex = -1; /* Buffer for macro expansion */ static char mlinebuf [LINESIZE]; @@ -63,15 +68,84 @@ static int ExpandMacros = 1; /*****************************************************************************/ -/* code */ +/* Low level preprocessor token handling */ /*****************************************************************************/ -static int keepch (char c) +/* Types of preprocessor tokens */ +typedef enum { + PP_DEFINE, + PP_ELIF, + PP_ELSE, + PP_ENDIF, + PP_ERROR, + PP_IF, + PP_IFDEF, + PP_IFNDEF, + PP_INCLUDE, + PP_LINE, + PP_PRAGMA, + PP_UNDEF, + PP_ILLEGAL +} pptoken_t; + + + +/* Preprocessor keyword to token mapping table */ +static const struct PPToken { + const char* Key; /* Keyword */ + pptoken_t Tok; /* Token */ +} PPTokens[] = { + { "define", PP_DEFINE }, + { "elif", PP_ELIF }, + { "else", PP_ELSE }, + { "endif", PP_ENDIF }, + { "error", PP_ERROR }, + { "if", PP_IF }, + { "ifdef", PP_IFDEF }, + { "ifndef", PP_IFNDEF }, + { "include", PP_INCLUDE }, + { "line", PP_LINE }, + { "pragma", PP_PRAGMA }, + { "undef", PP_UNDEF }, +}; + +/* Number of preprocessor tokens */ +#define PPTOKEN_COUNT (sizeof(PPTokens) / sizeof(PPTokens[0])) + + + +static int CmpToken (const void* Key, const void* Elem) +/* Compare function for bsearch */ +{ + return strcmp ((const char*) Key, ((const struct PPToken*) Elem)->Key); +} + + + +static pptoken_t FindPPToken (const char* Ident) +/* Find a preprocessor token and return ut. Return PP_ILLEGAL if the identifier + * is not a valid preprocessor token. + */ +{ + struct PPToken* P; + P = bsearch (Ident, PPTokens, PPTOKEN_COUNT, sizeof (PPTokens[0]), CmpToken); + return P? P->Tok : PP_ILLEGAL; +} + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +static void keepch (char c) /* Put character c into translation buffer. */ { - return (*mptr++ = c); + *mptr++ = c; } @@ -79,9 +153,9 @@ static int keepch (char c) static void keepstr (const char* S) /* Put string str into translation buffer. */ { - while (*S) { - keepch (*S++); - } + unsigned Len = strlen (S); + memcpy (mptr, S, Len); + mptr += Len; } @@ -166,18 +240,20 @@ static char* CopyQuotedString (char* Target) /*****************************************************************************/ -/* Macro stuff */ +/* Macro stuff */ /*****************************************************************************/ static int MacName (char* Ident) -/* Get macro symbol name. If error, print message and clear line. */ +/* Get a macro symbol name into Ident. If we have an error, print a + * diagnostic message and clear the line. + */ { if (IsSym (Ident) == 0) { - PPError ("Identifier expected"); + PPError ("Identifier expected"); ClearLine (); - return 0; + return 0; } else { return 1; } @@ -186,7 +262,7 @@ static int MacName (char* Ident) static void ExpandMacroArgs (Macro* M) -/* Preprocessor pass 2. Perform macro substitution. */ +/* Expand the arguments of a macro */ { ident Ident; const char* Replacement; @@ -198,21 +274,21 @@ static void ExpandMacroArgs (Macro* M) /* Copy the macro replacement checking for parameters to replace */ while (CurC != '\0') { - /* If the next token is an identifier, check for a macro arg */ + /* If the next token is an identifier, check for a macro arg */ if (IsIdent (CurC)) { SymName (Ident); - Replacement = FindMacroArg (M, Ident); - if (Replacement) { - /* Macro arg, keep the replacement */ + Replacement = FindMacroArg (M, Ident); + if (Replacement) { + /* Macro arg, keep the replacement */ keepstr (Replacement); } else { - /* No macro argument, keep the original identifier */ + /* No macro argument, keep the original identifier */ keepstr (Ident); } } else if (CurC == '#' && IsIdent (NextC)) { NextChar (); SymName (Ident); - Replacement = FindMacroArg (M, Ident); + Replacement = FindMacroArg (M, Ident); if (Replacement) { keepch ('\"'); keepstr (Replacement); @@ -225,7 +301,7 @@ static void ExpandMacroArgs (Macro* M) mptr = CopyQuotedString (mptr); } else { *mptr++ = CurC; - NextChar (); + NextChar (); } } @@ -238,7 +314,7 @@ static void ExpandMacroArgs (Macro* M) static int MacroCall (Macro* M) /* Process a function like macro */ { - unsigned ArgCount; /* Macro argument count */ + int ArgCount; /* Macro argument count */ unsigned ParCount; /* Number of open parenthesis */ char Buf[LINESIZE]; /* Argument buffer */ const char* ArgStart; @@ -263,68 +339,68 @@ static int MacroCall (Macro* M) B = Buf; while (1) { if (CurC == '(') { - /* Nested parenthesis */ + /* Nested parenthesis */ *B++ = CurC; - NextChar (); + NextChar (); ++ParCount; } else if (IsQuote (CurC)) { B = CopyQuotedString (B); } else if (CurC == ',' || CurC == ')') { if (ParCount == 0) { - /* End of actual argument */ + /* End of actual argument */ *B++ = '\0'; - while (IsBlank(*ArgStart)) { - ++ArgStart; - } + while (IsBlank(*ArgStart)) { + ++ArgStart; + } if (ArgCount < M->ArgCount) { M->ActualArgs[ArgCount++] = ArgStart; } else if (CurC != ')' || *ArgStart != '\0' || M->ArgCount > 0) { - /* Be sure not to count the single empty argument for a - * macro that does not have arguments. - */ + /* Be sure not to count the single empty argument for a + * macro that does not have arguments. + */ ++ArgCount; - } + } - /* Check for end of macro param list */ - if (CurC == ')') { - NextChar (); - break; - } + /* Check for end of macro param list */ + if (CurC == ')') { + NextChar (); + break; + } /* Start the next param */ ArgStart = B; - NextChar (); + NextChar (); } else { - /* Comma or right paren inside nested parenthesis */ + /* Comma or right paren inside nested parenthesis */ if (CurC == ')') { --ParCount; } *B++ = CurC; - NextChar (); + NextChar (); } } else if (IsBlank (CurC)) { - /* Squeeze runs of blanks */ + /* Squeeze runs of blanks */ *B++ = ' '; SkipBlank (); } else if (CurC == '\0') { - /* End of line inside macro argument list - read next line */ + /* End of line inside macro argument list - read next line */ if (NextLine () == 0) { return 0; } } else { - /* Just copy the character */ + /* Just copy the character */ *B++ = CurC; - NextChar (); + NextChar (); } } /* Compare formal argument count with actual */ if (M->ArgCount != ArgCount) { - PPError ("Macro argument count mismatch"); - /* Be sure to make enough empty arguments available */ - while (ArgCount < M->ArgCount) { - M->ActualArgs [ArgCount++] = ""; - } + PPError ("Macro argument count mismatch"); + /* Be sure to make enough empty arguments available */ + while (ArgCount < M->ArgCount) { + M->ActualArgs [ArgCount++] = ""; + } } /* Preprocess the line, replacing macro parameters */ @@ -341,20 +417,20 @@ static void ExpandMacro (Macro* M) { /* Check if this is a function like macro */ if (M->ArgCount >= 0) { - /* Function like macro */ + /* Function like macro */ if (MacroCall (M) == 0) { ClearLine (); } } else { - /* Just copy the replacement text */ + /* Just copy the replacement text */ keepstr (M->Replacement); } } -static void addmac (void) -/* Add a macro to the macro table. */ +static void DefineMacro (void) +/* Handle a macro definition. */ { char* saveptr; ident Ident; @@ -381,9 +457,9 @@ static void addmac (void) NextChar (); /* Set the marker that this is a function like macro */ - M->ArgCount = 0; + M->ArgCount = 0; - /* Read the formal parameter list */ + /* Read the formal parameter list */ while (1) { SkipBlank (); if (CurC == ')') @@ -391,14 +467,14 @@ static void addmac (void) if (MacName (Ident) == 0) { return; } - AddMacroArg (M, Ident); + AddMacroArg (M, Ident); SkipBlank (); if (CurC != ',') break; NextChar (); } - /* Check for a right paren and eat it if we find one */ + /* Check for a right paren and eat it if we find one */ if (CurC != ')') { PPError ("`)' expected"); ClearLine (); @@ -425,16 +501,16 @@ static void addmac (void) * Print a diagnostic if not. */ if (Existing) { - if (MacroCmp (M, Existing) != 0) { - PPError ("Macro redefinition is not identical"); - } + if (MacroCmp (M, Existing) != 0) { + PPError ("Macro redefinition is not identical"); + } } } /*****************************************************************************/ - +/* Preprocessing */ /*****************************************************************************/ @@ -586,8 +662,8 @@ static void xlateline (void) -static void doundef (void) -/* Process #undef directive */ +static void DoUndef (void) +/* Process the #undef directive */ { ident Ident; @@ -599,21 +675,29 @@ static void doundef (void) -static int setmflag (int skip, int flag, int cond) -/* setmflag( skip, flag, cond ) */ +static int PushIf (int Skip, int Invert, int Cond) +/* Push a new if level onto the if stack */ { - if (skip) { - s_ifdef[++i_ifdef] = 3; - return (1); + /* Check for an overflow of the if stack */ + if (IfIndex >= MAX_IFS-1) { + PPError ("Too many nested #if clauses"); + return 1; + } + + /* Push the #if condition */ + ++IfIndex; + if (Skip) { + IfStack[IfIndex] = IFCOND_SKIP | IFCOND_NEEDTERM; + return 1; } else { - s_ifdef[++i_ifdef] = 6; - return (flag ^ cond); + IfStack[IfIndex] = IFCOND_NONE | IFCOND_NEEDTERM; + return (Invert ^ Cond); } } -static int doiff (int skip) +static int DoIf (int Skip) /* Process #if directive */ { ExprDesc lval; @@ -670,12 +754,12 @@ static int doiff (int skip) NextTok = sv2; /* Set the #if condition according to the expression result */ - return (setmflag (skip, 1, lval.e_const != 0)); + return PushIf (Skip, 1, lval.ConstVal != 0); } -static int doifdef (int skip, int flag) +static int DoIfDef (int skip, int flag) /* Process #ifdef if flag == 1, or #ifndef if flag == 0. */ { ident Ident; @@ -684,13 +768,13 @@ static int doifdef (int skip, int flag) if (MacName (Ident) == 0) { return 0; } else { - return setmflag (skip, flag, IsMacro(Ident)); + return PushIf (skip, flag, IsMacro(Ident)); } } -static void doinclude (void) +static void DoInclude (void) /* Open an include file. */ { char RTerm; @@ -750,7 +834,7 @@ Done: -static void doerror (void) +static void DoError (void) /* Print an error */ { SkipBlank (); @@ -760,57 +844,12 @@ static void doerror (void) PPError ("#error: %s", lptr); } - /* clear rest of line */ + /* Clear the rest of line */ ClearLine (); } -/* C preprocessor. */ - -/* stuff used to bum the keyword dispatching stuff */ -enum { - PP_DEFINE, - PP_ELSE, - PP_ENDIF, - PP_ERROR, - PP_IF, - PP_IFDEF, - PP_IFNDEF, - PP_INCLUDE, - PP_LINE, - PP_PRAGMA, - PP_UNDEF, - PP_ILLEGAL -}; - -static const struct tok_elt pre_toks[] = { - { "define", PP_DEFINE }, - { "else", PP_ELSE }, - { "endif", PP_ENDIF }, - { "error", PP_ERROR }, - { "if", PP_IF }, - { "ifdef", PP_IFDEF }, - { "ifndef", PP_IFNDEF }, - { "include", PP_INCLUDE }, - { "line", PP_LINE }, - { "pragma", PP_PRAGMA }, - { "undef", PP_UNDEF }, - { 0, PP_ILLEGAL } -}; - - - -static int searchtok (const char *sym, const struct tok_elt *toks) -/* Search a token in a table */ -{ - while (toks->toknam && strcmp (toks->toknam, sym)) - ++toks; - return (toks->toknbr); -} - - - void Preprocess (void) /* Preprocess a line */ { @@ -836,28 +875,64 @@ void Preprocess (void) PPError ("Preprocessor directive expected"); ClearLine (); } else { - switch (searchtok (Directive, pre_toks)) { + switch (FindPPToken (Directive)) { case PP_DEFINE: if (!Skip) { - addmac (); + DefineMacro (); } break; + case PP_ELIF: + if (IfIndex >= 0) { + if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) { + + /* Handle as #else/#if combination */ + if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) { + Skip = !Skip; + } + IfStack[IfIndex] |= IFCOND_ELSE; + Skip = DoIf (Skip); + + /* #elif doesn't need a terminator */ + IfStack[IfIndex] &= ~IFCOND_NEEDTERM; + } else { + PPError ("Duplicate #else/#elif"); + } + } else { + PPError ("Unexpected #elif"); + } + break; + case PP_ELSE: - if (s_ifdef[i_ifdef] & 2) { - if (s_ifdef[i_ifdef] & 4) { - Skip = !Skip; - } - s_ifdef[i_ifdef] ^= 2; + if (IfIndex >= 0) { + if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) { + if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) { + Skip = !Skip; + } + IfStack[IfIndex] |= IFCOND_ELSE; + } else { + PPError ("Duplicate #else"); + } } else { PPError ("Unexpected `#else'"); } break; case PP_ENDIF: - if (i_ifdef >= 0) { - Skip = s_ifdef[i_ifdef--] & 1; + if (IfIndex >= 0) { + /* Remove any clauses on top of stack that do not + * need a terminating #endif. + */ + while (IfIndex >= 0 && (IfStack[IfIndex] & IFCOND_NEEDTERM) == 0) { + --IfIndex; + } + + /* Stack may not be empty here or something is wrong */ + CHECK (IfIndex >= 0); + + /* Remove the clause that needs a terminator */ + Skip = (IfStack[IfIndex--] & IFCOND_SKIP) != 0; } else { PPError ("Unexpected `#endif'"); } @@ -865,34 +940,34 @@ void Preprocess (void) case PP_ERROR: if (!Skip) { - doerror (); + DoError (); } break; case PP_IF: - Skip = doiff (Skip); + Skip = DoIf (Skip); break; case PP_IFDEF: - Skip = doifdef (Skip, 1); + Skip = DoIfDef (Skip, 1); break; case PP_IFNDEF: - Skip = doifdef (Skip, 0); + Skip = DoIfDef (Skip, 0); break; case PP_INCLUDE: if (!Skip) { - doinclude (); + DoInclude (); } break; case PP_LINE: - /* Not allowed in strict ANSI mode */ - if (ANSI) { - PPError ("Preprocessor directive expected"); - ClearLine (); - } + /* Not allowed in strict ANSI mode */ + if (!Skip && ANSI) { + PPError ("Preprocessor directive expected"); + ClearLine (); + } break; case PP_PRAGMA: @@ -906,7 +981,7 @@ void Preprocess (void) case PP_UNDEF: if (!Skip) { - doundef (); + DoUndef (); } break; @@ -918,7 +993,7 @@ void Preprocess (void) } if (NextLine () == 0) { - if (i_ifdef >= 0) { + if (IfIndex >= 0) { PPError ("`#endif' expected"); } return;