diff options
author | Robert Moore <Robert.Moore@intel.com> | 2013-05-24 14:27:56 -0700 |
---|---|---|
committer | Robert Moore <Robert.Moore@intel.com> | 2013-05-24 14:27:56 -0700 |
commit | 86e760ea9b5163994204b74719aba4c14a6d3841 (patch) | |
tree | 76ff8a3a0729c6afe4372eecea475aac41cd2634 | |
parent | 1e2483fcfef42d3adbcea32cc1ce1c3a98a1a7bc (diff) |
iASL/Preprocessor: Finish implementation of nested #if/#else blocks.
Allows arbitrary depth of nested blocks.
-rw-r--r-- | source/compiler/preprocess.h | 18 | ||||
-rw-r--r-- | source/compiler/prscan.c | 368 |
2 files changed, 284 insertions, 102 deletions
diff --git a/source/compiler/preprocess.h b/source/compiler/preprocess.h index 3e4eaffbb..351ff0e69 100644 --- a/source/compiler/preprocess.h +++ b/source/compiler/preprocess.h @@ -196,6 +196,17 @@ typedef struct pr_file_node } PR_FILE_NODE; +#define MAX_ARGUMENT_LENGTH 24 + +typedef struct directive_info +{ + struct directive_info *Next; + char Argument[MAX_ARGUMENT_LENGTH]; + int Directive; + BOOLEAN IgnoringThisCodeBlock; + +} DIRECTIVE_INFO; + /* * Globals @@ -208,12 +219,13 @@ PR_EXTERN char PR_INIT_GLOBAL (*Gbl_MainTokenBuffer, NULL); /* PR_EXTERN char PR_INIT_GLOBAL (*Gbl_MacroTokenBuffer, NULL); /* [ASL_LINE_BUFFER_SIZE]; */ PR_EXTERN char PR_INIT_GLOBAL (*Gbl_ExpressionTokenBuffer, NULL); /* [ASL_LINE_BUFFER_SIZE]; */ -PR_EXTERN PR_FILE_NODE *Gbl_InputFileList; -PR_EXTERN PR_DEFINE_INFO PR_INIT_GLOBAL (*Gbl_DefineList, NULL); PR_EXTERN UINT32 Gbl_PreprocessorLineNumber; PR_EXTERN int Gbl_IfDepth; +PR_EXTERN PR_FILE_NODE *Gbl_InputFileList; +PR_EXTERN PR_DEFINE_INFO PR_INIT_GLOBAL (*Gbl_DefineList, NULL); PR_EXTERN BOOLEAN PR_INIT_GLOBAL (Gbl_PreprocessorError, FALSE); - +PR_EXTERN BOOLEAN PR_INIT_GLOBAL (Gbl_IgnoringThisCodeBlock, FALSE); +PR_EXTERN DIRECTIVE_INFO PR_INIT_GLOBAL (*Gbl_DirectiveStack, NULL); /* * prscan - Preprocessor entry diff --git a/source/compiler/prscan.c b/source/compiler/prscan.c index a32f14c6a..ab89499a6 100644 --- a/source/compiler/prscan.c +++ b/source/compiler/prscan.c @@ -137,13 +137,27 @@ PrPreprocessInputFile ( static void PrDoDirective ( char *DirectiveToken, - char **Next, - BOOLEAN *IgnoringThisCodeBlock); + char **Next); static int PrMatchDirective ( char *Directive); +static void +PrPushDirective ( + int Directive, + char *Argument); + +static void +PrPopDirective ( + void); + +static void +PrDbgPrint ( + char *Action, + char *DirectiveName); + + /* * Supported preprocessor directives */ @@ -228,11 +242,16 @@ PrInitializeGlobals ( { /* Init globals */ - Gbl_IfDepth = 0; Gbl_InputFileList = NULL; Gbl_CurrentLineNumber = 0; Gbl_PreprocessorLineNumber = 1; Gbl_PreprocessorError = FALSE; + + /* These are used to track #if/#else blocks (possibly nested) */ + + Gbl_IfDepth = 0; + Gbl_IgnoringThisCodeBlock = FALSE; + Gbl_DirectiveStack = NULL; } @@ -362,7 +381,6 @@ PrPreprocessInputFile ( char *ReplaceString; PR_DEFINE_INFO *DefineInfo; ACPI_SIZE TokenOffset; - BOOLEAN IgnoringThisCodeBlock = FALSE; char *Next; int OffsetAdjust; @@ -392,7 +410,7 @@ PrPreprocessInputFile ( /* Execute the directive, do not write line to output file */ - PrDoDirective (Token, &Next, &IgnoringThisCodeBlock); + PrDoDirective (Token, &Next); continue; } @@ -401,7 +419,7 @@ PrPreprocessInputFile ( * FALSE, ignore the line and do not write it to the output file. * This continues until an #else or #endif is encountered. */ - if (IgnoringThisCodeBlock == TRUE) + if (Gbl_IgnoringThisCodeBlock) { continue; } @@ -488,12 +506,8 @@ PrPreprocessInputFile ( * * PARAMETERS: Directive - Pointer to directive name token * Next - "Next" buffer from GetNextToken - * IgnoringThisCodeBlock - Where the "ignore code" flag is - * returned. * - * RETURN: IgnoringThisCodeBlock: Set to TRUE if we are skipping the FALSE - * part of an #if or #else block. Set to FALSE when the - * corresponding #else or #endif is encountered. + * RETURN: None. * * DESCRIPTION: Main processing for all preprocessor directives * @@ -502,8 +516,7 @@ PrPreprocessInputFile ( static void PrDoDirective ( char *DirectiveToken, - char **Next, - BOOLEAN *IgnoringThisCodeBlock) + char **Next) { char *Token = Gbl_MainTokenBuffer; char *Token2; @@ -531,14 +544,28 @@ PrDoDirective ( return; } - /* TBD: Need a faster way to do this: */ - - if ((Directive == PR_DIRECTIVE_ELIF) || - (Directive == PR_DIRECTIVE_ELSE) || - (Directive == PR_DIRECTIVE_ENDIF)) + /* + * If we are currently ignoring this block and we encounter a #else or + * #elif, we must ignore their blocks also if the parent block is also + * being ignored. + */ + if (Gbl_IgnoringThisCodeBlock) { - DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID "Begin #%s\n", - Gbl_CurrentLineNumber, Gbl_DirectiveInfo[Directive].Name); + switch (Directive) + { + case PR_DIRECTIVE_ELSE: + case PR_DIRECTIVE_ELIF: + + if (Gbl_DirectiveStack && Gbl_DirectiveStack->IgnoringThisCodeBlock) + { + PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name); + return; + } + break; + + default: + break; + } } /* @@ -548,32 +575,35 @@ PrDoDirective ( */ switch (Directive) { + case PR_DIRECTIVE_ELSE: + + Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock); + PrDbgPrint ("Executing", "else block"); + return; + case PR_DIRECTIVE_ELIF: - *IgnoringThisCodeBlock = !(*IgnoringThisCodeBlock); - if (*IgnoringThisCodeBlock == TRUE) + Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock); + Directive = PR_DIRECTIVE_IF; + + if (Gbl_IgnoringThisCodeBlock == TRUE) { /* Not executing the ELSE part -- all done here */ + PrDbgPrint ("Ignoring", "elif block"); return; } - /* Will execute the ELSE..IF part */ + /* Will fall down and execute the IF part */ - DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID - "#elif - Executing else block\n", - Gbl_CurrentLineNumber); - Directive = PR_DIRECTIVE_IF; + PrPopDirective (); /* Pop off the original #if */ + PrDbgPrint ("Executing", "elif block"); break; - case PR_DIRECTIVE_ELSE: - - *IgnoringThisCodeBlock = !(*IgnoringThisCodeBlock); - return; - case PR_DIRECTIVE_ENDIF: - *IgnoringThisCodeBlock = FALSE; - Gbl_IfDepth--; + PrDbgPrint ("Executing", "endif"); + PrPopDirective (); + if (Gbl_IfDepth < 0) { PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH, @@ -583,22 +613,9 @@ PrDoDirective ( return; default: - break; } - /* - * At this point, if we are ignoring the current code block, - * do not process any more directives (i.e., ignore them also.) - */ - if (*IgnoringThisCodeBlock == TRUE) - { - return; - } - - DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID "Begin #%s\n", - Gbl_CurrentLineNumber, Gbl_DirectiveInfo[Directive].Name); - /* Most directives have at least one argument */ if (Gbl_DirectiveInfo[Directive].ArgCount == 1) @@ -610,8 +627,85 @@ PrDoDirective ( } } + /* + * At this point, if we are ignoring the current code block, + * do not process any more directives (i.e., ignore them also.) + * For "if" style directives, open/push a new block anyway. We + * must do this to keep track of #endif directives + */ + if (Gbl_IgnoringThisCodeBlock) + { + switch (Directive) + { + case PR_DIRECTIVE_IF: + case PR_DIRECTIVE_IFDEF: + case PR_DIRECTIVE_IFNDEF: + + PrPushDirective (Directive, Token); + PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name); + break; + + default: + break; + } + + return; + } + + /* + * Execute the directive + */ + PrDbgPrint ("Begin execution", Gbl_DirectiveInfo[Directive].Name); + switch (Directive) { + case PR_DIRECTIVE_IF: + + TokenOffset = Token - Gbl_MainTokenBuffer; + + /* Need to expand #define macros in the expression string first */ + + Status = PrResolveIntegerExpression ( + &Gbl_CurrentLineBuffer[TokenOffset-1], &Value); + if (ACPI_FAILURE (Status)) + { + return; + } + + PrPushDirective (Directive, Token); + if (!Value) + { + Gbl_IgnoringThisCodeBlock = TRUE; + } + + DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID + "Resolved #if: %8.8X%8.8X %s\n", + Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value), + Gbl_IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>"); + break; + + case PR_DIRECTIVE_IFDEF: + + PrPushDirective (Directive, Token); + if (!PrMatchDefine (Token)) + { + Gbl_IgnoringThisCodeBlock = TRUE; + } + + PrDbgPrint ("Evaluated", "ifdef"); + break; + + case PR_DIRECTIVE_IFNDEF: + + PrPushDirective (Directive, Token); + if (PrMatchDefine (Token)) + { + Gbl_IgnoringThisCodeBlock = TRUE; + } + + PrDbgPrint ("Evaluated", "ifndef"); + break; + case PR_DIRECTIVE_DEFINE: /* * By definition, if first char after the name is a paren, @@ -674,58 +768,6 @@ PrDoDirective ( THIS_TOKEN_OFFSET (Token)); break; - case PR_DIRECTIVE_IF: - - TokenOffset = Token - Gbl_MainTokenBuffer; - - /* Need to expand #define macros in the expression string first */ - - Status = PrResolveIntegerExpression ( - &Gbl_CurrentLineBuffer[TokenOffset-1], &Value); - if (ACPI_FAILURE (Status)) - { - return; - } - - if (!Value) - { - *IgnoringThisCodeBlock = TRUE; - } - - DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID - "Resolved #if: %8.8X%8.8X %s\n", - Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value), - *IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>"); - - Gbl_IfDepth++; - break; - - case PR_DIRECTIVE_IFDEF: - - if (!PrMatchDefine (Token)) - { - *IgnoringThisCodeBlock = TRUE; - } - - Gbl_IfDepth++; - DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID - "Start #ifdef %s\n", Gbl_CurrentLineNumber, - *IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>"); - break; - - case PR_DIRECTIVE_IFNDEF: - - if (PrMatchDefine (Token)) - { - *IgnoringThisCodeBlock = TRUE; - } - - Gbl_IfDepth++; - DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID - "Start #ifndef %2.2X\n", Gbl_CurrentLineNumber, - *IgnoringThisCodeBlock, Gbl_CurrentLineNumber); - break; - case PR_DIRECTIVE_INCLUDE: Token = PrGetNextToken (NULL, " \"<>", Next); @@ -868,3 +910,131 @@ PrMatchDirective ( return (ASL_DIRECTIVE_NOT_FOUND); /* Command not recognized */ } + + +/******************************************************************************* + * + * FUNCTION: PrPushDirective + * + * PARAMETERS: Directive - Encoded directive ID + * Argument - String containing argument to the + * directive + * + * RETURN: None + * + * DESCRIPTION: Push an item onto the directive stack. Used for processing + * nested #if/#else type conditional compilation directives. + * Specifically: Used on detection of #if/#ifdef/#ifndef to open + * a block. + * + ******************************************************************************/ + +static void +PrPushDirective ( + int Directive, + char *Argument) +{ + DIRECTIVE_INFO *Info; + + + /* Allocate and populate a stack info item */ + + Info = ACPI_ALLOCATE (sizeof (DIRECTIVE_INFO)); + + Info->Next = Gbl_DirectiveStack; + Info->Directive = Directive; + Info->IgnoringThisCodeBlock = Gbl_IgnoringThisCodeBlock; + strncpy (Info->Argument, Argument, MAX_ARGUMENT_LENGTH); + + DbgPrint (ASL_DEBUG_OUTPUT, + "Pr(%.4u) - [%u %s] %*s Pushed [#%s %s]: IgnoreFlag = %s\n", + Gbl_CurrentLineNumber, Gbl_IfDepth, + Gbl_IgnoringThisCodeBlock ? "I" : "E", + Gbl_IfDepth * 4, " ", + Gbl_DirectiveInfo[Directive].Name, + Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE"); + + /* Push new item */ + + Gbl_DirectiveStack = Info; + Gbl_IfDepth++; +} + + +/******************************************************************************* + * + * FUNCTION: PrPopDirective + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Pop an item off the directive stack. Used for processing + * nested #if/#else type conditional compilation directives. + * Specifically: Used on detection of #elif and #endif to remove + * the original #if/#ifdef/#ifndef from the stack and close + * the block. + * + ******************************************************************************/ + +static void +PrPopDirective ( + void) +{ + DIRECTIVE_INFO *Info; + + + /* Check for empty stack */ + + Info = Gbl_DirectiveStack; + if (!Info) + { + AcpiOsPrintf ("%s ERROR - line %u: Cannot pop empty directive stack!\n", + Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber); + return; + } + + /* Pop one item, keep globals up-to-date */ + + Gbl_IfDepth--; + Gbl_IgnoringThisCodeBlock = Info->IgnoringThisCodeBlock; + Gbl_DirectiveStack = Info->Next; + + DbgPrint (ASL_DEBUG_OUTPUT, + "Pr(%.4u) - [%u %s] %*s Popped [#%s %s]: IgnoreFlag now = %s\n", + Gbl_CurrentLineNumber, Gbl_IfDepth, + Gbl_IgnoringThisCodeBlock ? "I" : "E", + Gbl_IfDepth * 4, " ", + Gbl_DirectiveInfo[Info->Directive].Name, + Info->Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE"); + + ACPI_FREE (Info); +} + + +/******************************************************************************* + * + * FUNCTION: PrDbgPrint + * + * PARAMETERS: Action - Action being performed + * DirectiveName - Directive being processed + * + * RETURN: None + * + * DESCRIPTION: Special debug print for directive processing. + * + ******************************************************************************/ + +static void +PrDbgPrint ( + char *Action, + char *DirectiveName) +{ + + DbgPrint (ASL_DEBUG_OUTPUT, "Pr(%.4u) - [%u %s] " + "%*s %s #%s, Depth %u\n", + Gbl_CurrentLineNumber, Gbl_IfDepth, + Gbl_IgnoringThisCodeBlock ? "I" : "E", + Gbl_IfDepth * 4, " ", + Action, DirectiveName, Gbl_IfDepth); +} |